From fb7d76545e0ae0861576499620ea4ad0fac1c88f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Mar 2021 11:40:09 -0600 Subject: [PATCH 001/352] [Doc] Patch the schematic of LUT circuit models to be consistent with netlists --- .../manual/arch_lang/figures/frac_lut3_example.svg | 10 +++++----- .../manual/arch_lang/figures/single_lut3_example.svg | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/source/manual/arch_lang/figures/frac_lut3_example.svg b/docs/source/manual/arch_lang/figures/frac_lut3_example.svg index 78582dd61..dd0025266 100644 --- a/docs/source/manual/arch_lang/figures/frac_lut3_example.svg +++ b/docs/source/manual/arch_lang/figures/frac_lut3_example.svg @@ -1,6 +1,6 @@ - + @@ -48,8 +48,8 @@ - Produced by OmniGraffle 7.18\n2020-11-26 19:26:01 +0000 - + Produced by OmniGraffle 7.18.4\n2021-03-15 17:35:45 +0000 + frac_lut3_example Legend @@ -267,12 +267,12 @@ - + in_buf - + in_inv diff --git a/docs/source/manual/arch_lang/figures/single_lut3_example.svg b/docs/source/manual/arch_lang/figures/single_lut3_example.svg index 6435ff602..a6bde93c4 100644 --- a/docs/source/manual/arch_lang/figures/single_lut3_example.svg +++ b/docs/source/manual/arch_lang/figures/single_lut3_example.svg @@ -1,6 +1,6 @@ - + @@ -48,8 +48,8 @@ - Produced by OmniGraffle 7.18\n2020-11-26 19:26:01 +0000 - + Produced by OmniGraffle 7.18.4\n2021-03-15 17:35:45 +0000 + single_lut3_example Legend @@ -248,12 +248,12 @@ - + in_buf - + in_inv From 7b23231909f29be250e1999f98e7efadb350df4b Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:08:50 -0600 Subject: [PATCH 002/352] Add images for user_defined_templates.v tutorial --- .../arch_modeling/figures/Error_log.png | Bin 0 -> 220729 bytes .../figures/modified_arch_file.png | Bin 0 -> 106370 bytes .../modified_user_defined_templates_file.png | Bin 0 -> 44058 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/tutorials/arch_modeling/figures/Error_log.png create mode 100644 docs/source/tutorials/arch_modeling/figures/modified_arch_file.png create mode 100644 docs/source/tutorials/arch_modeling/figures/modified_user_defined_templates_file.png diff --git a/docs/source/tutorials/arch_modeling/figures/Error_log.png b/docs/source/tutorials/arch_modeling/figures/Error_log.png new file mode 100644 index 0000000000000000000000000000000000000000..89114ec8d2484201672a485ed7bb4bc692ef000d GIT binary patch literal 220729 zcmb@u1yr0#yDdxvmmmRx2X}XA+=IJIaCg@L!QG{S;K3Sq3-0dj?(XoD%w%T%x!+mm z-m}iT7Sc`eO7&A!``LRx6(l1i0uO@;0|o{LFD5D|2L=Y|4F>jR3hMRCJK-wG#xFl! z*~y9UgMo&ycVAw-HR6-x0|P6IfPK&fe|ZgUEvjk<28L|^^Xt`;A)YfB*mI7UAfJM> z);l_N%L;)LH*-xFtAdcH<W=Hb^n8w}TlN|B*SLq(Abu!)XM3A3=0QaXMrE)2Xrk^ATOO_NsSnFg z%byORo*r?wLe*$~_3F=ad3ynu7rl?9FH*~A)tN6>F~pj)p4eDJ|wdt zy9Q&`q8&~5&Xo60|5!X!eH__cAnz^6%V_Sdv}{^kJd+>|Q^znhpG>_}%GYWN|3pzQ zN!nncLEGM@`HD8jh>KK=D-xPmi*%hUf<0=~6;7)=DBr#Jz!$E_@y}bonZF$%{njqx zinioZs4%=p$C2t3<~f%a=VF$B7~h+=pVUNyKyT!T!Gk0z;6JW#?*`YjXCaGl{18QK zHCNR-hWL32=R=#KO5%_XgvgP< zwBq#9#$}KNVFeK_-h6DT68jOJ5Ou7i%A}^tG2<-pX{!2m-%(>Plt41j%=87QXmM*!lM)Gs#8iR`#5?Nvujs66%4t!?ja2` zNOMf`-KDjxB!lBW-6NBvXdOd{Fjp+w(zFL>CKi|iMB2(TC0R|o-mIf?KJ4|sTSVKQ z|2cwx9^NIS%id4R&yU&wwUaY=<6A_NNy&BM*RujVzltqfIj;A866K z>>fd%O~v-qkGn8oV$NE2D!_dY<50QDy`Cg-p{=p;`F@st5O&ajGkqKGG|W3BBZEYU+Ebzt_Ebe;ue8bkX_@3!BLnU$9BDdJC*M`jCQYh*Okt|>&Icc_Z3 zY&5q{CfI3d57d`KOPwz{ak&J<4DDmEGh&65OBbXOL(7#%Iw85J^y-&Tze%hmKqg9k zKi+=b3x1$)fowJoRAsLeAG$Q}_w0<8@kyw3^#S@H`e)DBC46zEVrrM;We_n>R>;m! zVpM^E%Yb)(bX-p8KO9YP_@g7iz_fYGUp=;<0wSCrAu747_fWQ&Bycq-uQ2RSZ!m>> zR|3q8_}WfgoDetW0ul>WO!M~U$*YWE7$S~JQ)jVezU_{`yHkBiML{uV38T<>88+Z% zvikc~2_J}gnYOvbKd`1@(v%|$sh0Qj>1d++-^?w!nxlYj(|7eTMAx4iG()CKPhPq$ z&6bcqVBQrR7iG2?Nu9igIEfjfpxa-u1SaY#iZb@Z20ck-t!RtQF}B|n7l;&4_;9lf zVO-duaur9|=2$urziuFeV0N=ZMJ2jUU1^8Sxo6uDF<&A$(ySM#2LQ=n5n46OI)Pk= zNFI&D9Z@B}6gBw3TBsozucE@$>@UmE zbJ(c6`dQLPqoMVQ``+t$@fKf`*^jb78D;X5jqhidjmMKCM%nSa^w;Tvt8Gh;x`QOx zX!3+;d)hMZGv5YoEr>v`Pt6GvDRQd_s+QyNfMZMdE)1!B64<#70fx5)^NW9YKJMtt zK%aikks&~eAQDAaIjDm*Y(v{Lk-sbG3a@mw1*wL#YxA{$uHDgw@EwYc(oktcu)9Au zf7@ea%C=J%~2k&FwJJ8jaXNjN7-OuAh$Pa6zexK@o$hC6D*K_zKI7Y`# znL=|;;;VoLBQX!hnV#p$Z8o{C4cSonY_=zE6ISp%G>&)s zbA8-F)G(ywvsFlAx^%u6a=h&NlzojrIve@v*ifmwLEaryY$OR#jCi}%_Z6ghK7maCkd|mx}!^-dM0^Gx(*1iJeue_850MJe> z9psuYF3DOEP!|vN7S6-3BL?*U?-mU^lEwO%p~!EDBCw#qlpL`lN!y`Ci;wG%!SJN* zd4h2H2e$E9n{bAx#6P02>c|EQ#;8yDO7`$ZUd5FX-Dk zLTEFFU^H$FVwkK*(oU#Cq05NOk$2E4_jbi*Gq;9U;^|1=3MpN5%Z(Z1;1{mQa#OiR zY+LEzn}3be`X%9#B6^{WLo0ZLfs~ATWZfqLia?75$7G!HLR5p+M$qPs0Hf(OF&sJ9 z)SwZeIx$HOcM-JRp*_`!OYdyHaPJeh%Uhc|rl2YsdPa)tgtY~TXlt6p#e-o`kK`n# zB9n-1tOAppBP#~$$JXrM@vsu1`!YaC<77k|E#4%j%igo7eSz?MH}x72e-+^$w>+yE zu8CqL{jhLx%>FfLdye=Fd-06AMacrMtup}^c8Zm9SE6`x;6l7=Q*fsN0xRs=Ko(mO3zKWa*eNS?R)IFWCt0ofx1$9K$NGkIA2kO`Xz4=%gu{gc14x>1; zP?P0~R3fI>H0OSDK|RF&u`@}=xDU18g_=-tZ7V~k+jkBmcsmpQPbuF9wsY!qwx0?Yia_Qw)J-E zdRnqe@IDY1D($95gBI2c(Qp5Zq7z6YOWys_9!i#PxAYFVTsdlC+%>`90cK~u-|?Lx zni6Td8*2co-KFo^&|HXU!hK2aH5#&$;@qqFZARzmYx0E1B6i#6=1Qdpt5rleWjE?W zt1zq3Mxz#AW93HBj#b-54IeKcprVJmv0&@hEZF`m(k2lEhoQq?%34C_dRDh0e^;-v)(5L9MllVij*u@ay=`Yr)Ni z_WPXXJLp6z=<_9oMC$3KVl)rm z`yKIZ)RV9*NBtgn4@fugI{|FB&^xqS{1M$(tslTnFrB+$rl*`vXCRnv8h#x7p2cr) zN?#q`^tQ~RgIW9IJ)Aux*tEtzwCntZZ67daydl86z5Jh0p&le*Z@7KEU=jGG#qw6Tj3CoDl@4v5@wL(;`Z*M)v&TqQXdOaL^!m_a29@5G@ zF)Wro{}aUfs{6Gx(~DauJ>^@rGz_-_9KT5Yz9L#Z3w;TIOuCf}tFrA8OIV(z&~>`!4W zQ4iaX)y8FXDJ`m6#qCY**JfwV+n3LGT{2KDpq?OXz{nVHa@j}84XNn}f*#4D=T;e7 zU*Q^)Yr?0i?3RFk`ke;-D7^WJ)nM?jWPAHnq-`u&z;jmNgw(r<`7L*L% zUNFjp;ZXtjOZkLlMTXm#_(6lKgLLP+vu5)>RK4fi7&trL)wgQ&c>5c}Z={=&Pkv$f z99Y{v>Xv0^NNFifT{a{`#zelT05V_lYds2HL80Scm{h`)k~?&yleyh-1g>_i=yIc% z6NFdegei8SL7GDA2nygno6A6{pogta1-8GHHK}d*u>@zZx;33ULQB{bsX+4vP@Jjp z>Ee}Lr;vauPF?+G`_lvqw|ll-Ke(PHc0`wluvupCQde+Hh%Oy{?j*|^%xKO1-3zE%{hYqqYhAjr2E9l~mS44+S)>j&!MN0mpjHsMpJT~C zwypD7#&%7o9Ss-1eAWPoWuGLf9Va>)mvKs=oFc%VrG;BOp(m;*6rJ$EruYQWM#bR=nS)Lc(u|7^uSL40D;2X*St)kwb){pq1BZ~Csoz_a-d(IfKU0#KU3{uMn zZM{d^iRUuk2&Z8fI>3#{%NpzJ#5OgmUj>PzREKlE=W^%b3cJsC95+fLtzN}Z_MuL` zMf&_klIX}TJTW=A%ZZ+>hVVH<#JzTMfs*x4mE&nbKxien-RLtUp0#mwdaB zQYP6aG*yhE{We7HdG!d3Hs)u>RH`>74_-B9rLow)2*1PA~X3xo7!5nxM_Jmi5%leqh3vv{xZl3#e0KMtKvbW7fT`7&(D z_M0!YT!h!%hJ0PSW%!}dt4{ENE-8)75&O_d0pfJcgMG6u>KL zTvkO^6ngzRRfYXxEt#Lxey3xV4B5XL!+hOk0@iL-+LA>+%?D~4h}*S0%o4;~p-1Y8hR*59*W{|RHB zQqY!DM>G86*86ZFZ1)u0M>+NTf|k{!{g zbk1DeXntU+g~_UYH}ThslkL9!k|*4c`JS?cLcEn8;l}`xf+GR01_oZazkNE?BTVsB zWS<5_nO@e?{Q|}h(>WNouETmsa1)PEA<~Klc21DGOuiUQOM*#zvjZjlbI^%0J!APC zw5q%S1Z2sl(Bfz+riRR;#lB4~*eO&$zKsICbj|6NdQb`c2~2*J?Jeg&_aG1-~CJYhc3|R>=1; zO6QDSAi4?6yU;bA0M8nf){q{Z1e1EL;hzmSWBekdJ@s&$R7$I{To#Nf@3~9RCUvJS zY3_kpsBx`FxDEN=sTx-O4N3^*3Q6f>h}8fV97#IChl7|TInHL;g>f`EeF)#8w3yhM3ju`;2OTLPZ%KCOS@f@=9rzsXEB3B) zXGz{+Z@AyQb}t`h&sEfjrrF~bvk}7dS2G*z7Iu<9M8$LLb|Dq$TI<6|krYb-YRHlP z-67TPTPP#i17Fh?=22L|Rt!%3(LlwF*vsCY)IU3Wg>8rE&ye!w!7=CM^gOe=0tW-G z8r?{tTF3SWU?y~X2*ZZ^O8s6yZ(x6MzwQ`3hghgSCF0J6|2|I(?0>+ap6|9IO24{q zed6Yhn{;v{gk=1UtzItwWBfl8%)f*Eg=DMwPjL7J;9!8RpO2oT%Zr5)BU zZM1E29)ir??9cjGs*HpkLtX=U;-p(x+xu=4ZtppQs!p3$*e|rVd@Ca0jk|{jpUG?b zFSVX-<{!}{6hM#Q#;Pnc9UdhOz-#Aq+p zT_re=0vze@X)`o-`g@;#Vs8)!aaBRSM=7C!-%=@8ab-x|DzHVE_Pz5Sn)dBvDu8BV zPFoLdP;ug(dATj3nD$Jz-Uvc@mPtC^moag~$9@M~ATI82^1M$7D^B3xj5!fq)Fp~A zLXSsW2>^cy$aUC9d zAj}iIkZU6+lk~bn?jBm4cPe4DA9M*kf?LD2u zj%E#n?wqtlMzO_20iM()r`Vek?@wz6kGCTYpO5-n{J5H~iH>dK>0BQSm*kPoQB&PX ztNrS*xm&bLw(1=HCJu8Ws|gB3;V#$&wMfZp)3^npo%=2}Cs;$P08fispyBG8s~g05 z?qg@RwRoWP9r}9VFfeW3 zfF8fy@P^Xe|5y58_SGLQFaPTLgX<>EaeIkTqt={eRHXk&lk701KrIaHIL5$A&tfF0 zb?Ly?w8$M#t-!xy#$Q|(GJ1JiB;ivdDx3BHobvC*9)0Whuui0Cy z@;R4SakNK!S#8ZBedW&9Ts&Q57D7rhXWf0YhAPm1z_-k`12p!dNbgFArH>da?ixv@ zE-}^^jI{8s`Oe;Qr{SJoY&4@heWdbgHU!LSSHJRT>T|RDmGjVKgY@n&zO&%rLqoCj zknQcb)H>Q)An?$Q0`h;P`|W;Vck!gid4t2No7%Gr ztjiO_k+zvbFp`}i8qjTeN`MD`-}xhb6SL?HK&r1boIyx_r3|b}<8tY?^@#2P_4d37}!C1Glo zcx0TkVWfYSNiX_Pv6#4bM%TM0;3XkRRRO7NV_Je!T-QKRTS zB*Y@$KeCF#^=DqTJL*vDd(6vf0jMx!K!zb{M*{3=-@p+fE?K|7rs z8ltv2kgFUJ4b787J4J83Z7B|KY2UEzWjeyHOoN3IotfxEFE zL`e|pA{Imc^(~3WiZSD&VwhmG4w|ExZ__n-?klDRN1dPv*Oeg8$!*yW;lVo|%qsHp zH^zH@Y>F&LscFh?OJd|YwXyDb!<~b(gI1mn+jCTfbB3lKu7@QmCH2uAb#CUL`bp)P z-sdQyO3Omzbm87~+g5qbLoi93nsqT1p%e5g>wmp%jGV-2dj$+S2SC{#`iE#{{hdVL& zEQuH+wk2X%?}T#GpyUz+#_3|Nbj9#)+bhLA>@Ih6szR2RE%2dL|EH`I^(82a^%e!5 zLdTI$nG*?f?~$j~?TlQQlhW!>UnanAPEV-MA1u)nl~c4QF!op+9z)zv6>;o!(QH#4 z4OJs|TFek|Qf&%f1ZNgfRZDJvuh{D%!y;Y?+qKXa!9M#k6WB9S+4r8}av{*x(r-~m zmqlbZdBaXElA7A-G$0O>ZP^;oP`TC6H^hiy?(1TN= zZ)22{4?>D8Bh?H(znjseslhGvbRarf?>6eVeS$cV%9c+p)4WEyH3OKybtTLeH26368CU+c3n*^tYK; z<)v=eCHt5TU-#;S0fSS{7pFbp@?5T5ti2+L*A!Ixb{&VGG_@fT`n6_l+4;0{*eRAlDL+CT%Bq9XW~DRN#4U%-|o28_n&mPeRR~>B=T_NkI8m;#GzQy z@aU>RnN+I!2Bjca0e1^4KsEIA!?1lhT=wbnBB;|$<>p0hlCDF_Xt!v39T8-{?5|(a zJzh_c4f~RiZk}7K-xV08Whoo4jn-&>6X{-AZ3$b*BO|z~^v%YF2@4QebT-_?E@n*vCqQULRXw#;h}B{cNu{GawvHd+ z1h^)s9_e3Hk2VLM?SXCz#iGabyoT|ShvT|AZx@m`f=TR5Utma_*^8M;kS?ih^9t zd)K8L2EGU**jpLKDH0dxlWDHTGLQct5T^nXZaJf#i;^2oV)J+RgSN5Vj3}w>NR(2E zZjH7QJRFYOXEQigs|llrYQ{_Jp12+W-hrIvlrJcTlGatqh?;B}6|$+; zwom~*h}Y_zHidUcWLIKr`Vk>1|b^zb1X zrz-y7m|k~z42qs!cNajoDu+0GF|g^Yhhy8Mc}J+C-$stmoIqg{<0db-1nP+Qt-}VY zjh%lHx7T5Spd_6&8cUgdE!pJ^;(VzQr4)ek4z40S-yxND!TSh>8Giq(#B}-}G*Y`Z zYR7vs;I#b-+W8ssHa z>`K!uqIQYNmgWX2!#*u0{A8rHbNn@_$->nNT`5(9V?bu-Fd43)te-u^En8Xe!}P~G z&L+`I6_pqLvt;XgSx+CQhW|}^i2L4;*iVBL>at1MhM;w|l zqZjY^+Qi{QE>VI-R);EL(TcZw#5)*R@&j>%D^G`9&ebAA^-l`81+?RQ=XE1pjao<$ z;ZK>x&0{|4#)+T`-zhuzLdz4M)eh-jG`56Tsu(Cny>};8CGE||wwVqtt67Ps0WE*u z>jN!4XmzI@GyPB`0yarg6iNv%j^zr+g+F?lda^Hbq?PZOloEU%U=(-f9n-!d9P_6s zv|fh)67$YTcd@XCQAlxGz1S7o<-2krP;;kj>G7c3<~;c7;Y;fK_-dN6jN!T|_OPrD zxh1FlF>47qB+}}7?I_x0%)*sn<^5Hpo-Zjy!W!@~#l2ONxJhsGg^{zeXv+NPfhT1W z3$IT)dKF$%2UUs?0*Wv8!eO9%xo}yxLrNaOu_zN}W-1;5@rZbO=|N%J?=3}f2Ds?wB8l9g$fA+#TYAuIR8oG#;eBz1>Zx80z&z|_0?wgC3 zvHLPX-E*w>^{&@1!9WwvU*o5e1!$a=f+~MaQQLEGjYLHWD$3wO0W>MVTts!%%mu#@ zd$imqG1bb)=UXpG7@$4zkjr#0hNpMQb5czivBMuB#aWbbsdAFvu{blC(g~OJ7pBh_*LrS$%8XO$kw2lyespq9zP0mJqF!Hl~8vbY(M#1Hc`^MY=Z8=K@Q*=y+Up zM;k>2`m{QX`Gy^TMWwj!7i4;r*=}$+(VK@#xoudYGrbnX1!~TvT3#iT2tE-g9JqDT z6q!?cA+%4^TguphHK&jM9h%CSfRE6}L8?{eS z0UzqQSVeUJjvdUV{Qb;zr5t|Q+Ss3BCs8~;v`;>%kPI!Lkjg_>*1akmFXW_Hk%^RC z05VaY7ImYF%V*(?SXQ{2Pf@%CQlc1f@ibyyy2}!u*l>r?3oU3*zCv=i*It_%l26ut znf)=-_fU?_JA&?s7H=7&dt9QSYw(E5=8XiS`+F&m9n_X~uJ~Tw$~lh$ij)RUsH_(w z({QjPdxlCg^rE779p}#hDCgj&F)VIiZ zKK7~H7DWf#)6xGeQRqw9=ug=YOATQ}~8o%2?JF*ESF&zCw5UF&DL| z0t=2EmXtn>GjCv0ahS&V<7|0f0kYE2Epci#N;#5%&GAyQ4eBX2eIZ4oJ99a~s3edh zZ3E<;^n;~03Goe}TC{XDQm}=oMNLR%z#6wrHCM8)$#3q55qi!dSt(I6ICO6JSH9?$ z`32+jLsU-nA|Sq4Zntd#Z+U2na%_3feeuspNC5gRJX6xZ-0qQwIV54IWSYpTdz!KW z3gPlnT_R>iNEM&!x9;%T80PdLvLt!ex2Fo6vM{)Le5(46wh8$w`?heq>;x93tAtX> zJey2EsN(|Gx6I4$cB)$Z+ldSXpe2So@?Qrb8l^jXLY-C6ti159b#u*ON}{l5H+KQ>>els2o18JSWWPN2e~Q{wfIQdZyC_GWMC*Wm0kSM!u!_xd z760O051v=ENtbM4Mn80vSGtc&5JS+I%36I5z@}aol0i#x$T8YMUmX7ccdlB<9^``_%(nAPB92@Q=$&!hRz0HBzp(^Ps z(^NZXE(x;q{TWH2uZjzjLKrEvb=#5}XN##QCHvW>)rYyra^iccGRcLih~Wo19c2Nl z?Qyi`6njCVQFvlg@8$h$%Zl#M2+J;Kkd)=k%b88&2y&fz$mR9wv>I$NLk2`WO%udQ z7sHn7km`n2`Uh2tuQW+#<2hv1YZ8~ce+Kaj{*k`4HQXYb#_bLE#}>Eq*Q8ZWy$}t5 z&pln1;)=DFWuVo|#q;`Bb^5UZYhMRw z#Rz#ek}kEv>VB8X1ta3vNhiZ_<}+VdzjbQTjU=gPJ+;SdrKSe7a@7y@Y(tM3MQDsO z)FFkpT*naS1ASuVc&Xq7ARQ0O{0tVm%HuBkpn}A2wF)b2Aq8q1f_l!#4h3IN(qddl zq@2pF9VNxpcm#NIC%GN_msov@7F?^#QrB~~-!K}(q;b?08&4K$NkaqD=gCQOv6Mgt z=B(mVOdTwv17bpg_m)NX57m}%NtC%enhT)l-F4WxnPk(2;6bqpm{>mtpnds(FX#l; z4HM4Ej_C$h*-ec$mH3(ir%-j!E_UA1_G#!=G5eV%z3Wcu16p>y%%_QLTk4n+U^Z5R zYL6SU#Fz2yx$&kx+oO1cA1@POWl%#g*=of8MwDe`DR81)n!cDst(1bo*yYW78U8T6-w3{xr4XgcKAOu_C0T`pX8hg0Z7&3dYF;_COA& ze5`G=`{aQNXwR#+Ap_wsJ&@4cIMTJe^R@gbLj2oDLsI(c5%)%Ul#%;911N29nY!51 z3inGPaewEGe&OVM3%>oM@3x^;z7D)_@r=}QJ$)DhYvgY|x!z1cDr z-$Dt<$H?_0S^2QT9?e;5(d{F1ngmKzxhiTQ6cK)Dn>W*Kj~p24j<=Y#4S+&Cj#N%! z)k~&{>%^&I)<*TT-E135fw1EGiY1E4!f6{Zp_<*F-2Yz^9T?b(^y((oNJ71dO0CA@ z(f0Yn3A*OaDb}~_egB*eOv+l&Rr7Yy&B77pnebX_A|u|52i|#m&=Q~x7lOfPld_e4 z)R0l0$4$g8^pgU|Xpli61g;@_%%EM_-S4Vb+FPdlcNDnLKksJW+qwAYFi&*&AOP>ktpA&}WnvK|32hE<=z-JE|0?ijj^hNOwt~6RuRO6BQVS;RO1BRbdt;c zQCQFwf^=1@lw4ka9&V{dMyw`Te+Z4$x zn0-h$^!CqWDj{;s{h7q*f4a15hNHfQ6bZ`4QIkt^P|9e~I!ZD9>k2=gwRx*I|7Zvar*iFKZe=zU?JH>!&YcIuO+<7(*_UaZm|HB&f`iHW04<4I_ z)pKz<3@iN4GzSNc|4a~+sZ0OM{6Ic*k^PYXXQkZnHOc#O`+}iQXfhFR0^m)`N8g?1 z-4d8zzl{1ykS8G`H1xBy49@+JE$n7YyyP_f}K6`l3S$>(+)w#8(h& zLGvt2IH^nRU>@e9``KomJ4OI}YzMVChrAg($`_!r1v^r1(+?)f8k3(c1s1nNKSx6Q zh>h&-wnU=T%XgvYS9hg^l0PAHf4U!B^>o&pPwf}|-V6K}Gf*|TW;8{2XwWdl^oQ|g zBTg}6GQerPd|=nd_?*oYLkfCp*^s|nF)#OdW9Qrs!E_wIt4siQZ((pBPA+HXiKQUa zs_xVXpT}QA%sR$zD{~tS&K-Lywy*~>Z-X&26ByQui>pUeI2MfBXP7dbP!klXmb6IZ zZWf)_qKjiwDEe&h56?ijB`?ZP4Ae0C%L1DmH_l;z5_A#3*(+MKry^m&F5An8_SNm4 z2YK@k59~j>?+I$@r8)wECgfd`XZ-QN@A8vhEtj; zo~0I@wjM|wk^jD+HxJDJu^#<<9sDo+q(gR1&rU5`7jM03!OVW2@`v)5Kjik?x}S2p z&f+5)*VOi$_O}P-Cf)AUf9UO$tevH^*Eu6T>+{Qs(s;QujH3@*bMJhaq5r(QmBO1B zMf+)Bi9DrAQ9eESmzy-DD6Lx6{U2`9t8|zDftxhL{FBfo;{U`>D(4gXSbvA>3xP zuXL`RJMmMJ7T>c}?^b?C|^9 zz&d_9HdX~VVUHUX3$`s^q~eI(3%U|y&myY^0|Sw@4njacB4a~ndSEVoyGg+#z+daK znylFlwkP`9c236xir#7sZk2*c!idh7&`F@iB<;5{G>-cJx=#L6DkkM8Zd%cDdR>7@ z;TYWwy$v{#dP`E!H`1m`bPLTfa zqH03@;YF1wd3R)Rp4syr2~bOqXb~wpF?wFA8fj+dT+!j~dNs$w@ae2Ef*+FOn+2O< zpHj%)&qepZ_hyKC<)UN^oP9HX*~*YGAK4#8m&F(3y-OfNqAgGEYe9vJKkS#;)oblg zni`Dekb~ZoLu%4#jq7(dZh28}haJjqKX1G45SHL@&|_8T%=fZOAjbJOz#a_BptV0F z*Nb&3N0_qL*m9dBOzU8@4lo~D3|>;=q0+QQT=;uPd!Qnzn)1Kz^W=4vsy7wi$mNP= zG}skj4FaI46{dDoG@`ML+~|6SeB07AY;b5-tUT~`>S#c{`IYg zdsmeL{`99szwF`Gj&B> zwN?DJBDird*0i@Ac@+g4($CyWy&REY1}!GK4KGVcGVlW&avPK;s+}yHkwa0qGM_5k zIL8!VW0;K^N!vGURFAl7Q@)&h`z&3gqpVs`v+9~-Y`l_nd$Xmkz$`o)gZ@nDv`ami zu{D~3Yv40lIcE^|HrEf6?&&s!GV@I-QFx2IxM7JD_Lgj{I3;0GP*_H6e*uaf5{61G z5S%;5dDFegw!?;uI6f`H{x45ETkEt1@3{2rWhJr@ZX)H?sLCJmRI571P}^YuoR7vm zqCBd`p@IizYV);kqKMPX&;h0S$i*(?Bh~Xz5Hw4QFe=TPq{8s z2Bn{DfRW(R*XU2imQ>>3eBH%=ST7!0CFC?XcQ&V7kHY zak66bq5!C+`R_Voc8%S*uq_~DAJawd#v!BO|~7RHD(lpo+m5_gA%ehgnc0VBT`>3>U;RxUPxR= zJvuYFvS`gA+X?9PZq-9B9+kfeH>_iiU;Mg|XU~@9#Pb28-ji1%e>zzO2VeQ5M$ea; zFh3&OgER>z_iS{dYhUGJaKq$rUlbg0@6XzNHyi59D=4pP@TE&`g~PPUl(;nCnl?Cm zD?z5etB{&N^$iyi0ZYSo@*hAhJaY742X_kKN5^I}Qq3!9y<*T5OypD)j?SlAG_APn zgUiTJpKo*+!gBv`$(a|&M?U0%8l^U`_f=2`*=TNdvfl&(MSGR4jOB$fc0X+pPi%FL%C$#?DkJG*o4IcH6W&^!<#&>HeId+ak|^Ck&Q711S1WHhdv zTUV7(2J2!f>R4C#vuOLqq`?{qWlC971i^FcdhHjdLUY#!W4EdE8EZZ^!xxCUd4VQw zWbJRaMjW1V-QtaN+vW$I`bdy>-#JA`sZ5q7&e>*0`%=L;HQ;w*?_?L&81hG67^9Y~ z^wjSailZr(tpMGGa(pi93|OmyC?1Q(3nG{?8nEw!(K4DayD*r*W1>UN_#1#0j6vj! z8vStS!TOQ{u8~Wagl3CsZJSzQM)P5sLIVX@dZwu##oD=-HU_T01B*it<=_4$7Ngs-M{NbL2wW@9ZYFzUZaY{c8HiLOH zK2%yYfDtC3S3_WpJR_HAu>WrLWB!++^?`$DYae;xS|8Y6-@$UB-H)Y&@Vm*0(toI% zx&ugf#q^&hMUZ+@6doT4BN!t7ZvT>b<+c9YA>r@izcR4?-QrI|Xa%co>A69h*7dJ( z0d`{K^KYZ7In?G)JJW);Sf~FwmltkJ z!>h&gB2I&f8q+e#`o@7SLcO1?DASKMWc z*U3jKN(*>Im@K-sH*6+JVb(BA%oK3$7t1xd;v^{8r${-@*J}BHZFsHK545w`?at^J zveIsjnO+dW)2k})`+PdbPFn|Y|NQFAtI5PlWPFu^({F(j_00UZtR#`|v`m6x+SP~U zu7T`#AD%#SpF{7Qj3$3|df}ezSVQqj^C0)quS^VMHm_YG8XY1y*^5-f=e0-mx$oFsPc8!zEECVs z2fp2?Xd%?G7#1xq{>83%51$xdjZ7CFpsI-B3Fn=o@h>Wnsly572JVa+9sjv8Ls+Or zO1nDd)_BEqb(CuK_96nu$SVu=?{X}H3Qn6%!}^7-PL{9oyy9qj$X|A4V4MfU{V#6H z(88X1%r97-~FsiP|T8h-t7rUcFmYXf(f;n$+O%(Xxf{BMwi~9;r(T|yr2LPes5)Adx!CSA3eY4{z6o0xnUQaE0Gpll)!v7z)U5F+_F>r%N`1IKr!7S(o zhI;78LnNgoR#O=>J#Lo1T2`5;870qVQjtC3Ii4V#nd=DoR-PRF0*_PPs@z3e(~f8` zFskGm>(UqyIzDz)7p)?4QEY>4`;`=DbDv|N0i_easmkET?F9R*u|B95@EChm`dI|e zHn-bn+|cfKxi1)SYoF!YuF*VrvVSk3O(*wIKO2C>PnN;Cy;ZeVGvuG}x^0qbxt0_54)=O4(TAkRrG#2i?Gu!{Tn1)#T?SsrWBUPc8FR&hW6> zFEvi&tOWM8#mX!6QHScP8~aIH_8ga3j;qWgdz&&(z!kac}@0ZQ-Ig+YF-U@K>nU5_?xZY)E}crwBNj{K-=)$%Z0~2I!=)}>$AdSC@ zp}1O=EqTxJt*|88Rran)60OI5($dk}l~2YS`aeaF=;=bmn=xh!-;e4)F`CHhqen{u zS|g?}YeBfyQ3a+u%jZ~1qR9=#bEAEx&XiHzCfu8PwEB?atSI&PPb+jnt_uUVtvl`6e!dYo4L}jjN;yRUC;}9=hZMGhv`xavHd73A zoM*@Ce}{_D5$iKbLitWYJ){S$BT#5II!Ey%B(%eOA!GErpHz*X{Qwz5ayGWadw3Fy zd|EEJCECX3#Nvxk4UJ`;MKp^wD4l*WmNFZyxfmaBFe6Uy24YMxV%y5ZK zJpRugdH&UH`FsjlDMCIZBnK2=BbSI2f!kBCNO|jOuAp481@t3It(gA3Q3DWtr>CSyNA^qyJ22c68Gx?{Vg@WRd%BTHdGT;f#O2+@;Y75D7I>B<~lD8j_-FFv@4K z)w(`9WVJI+8Aksgc$-zk==FRQt9CFXdMp$ubAYhj^fFVPU@WnJES91wfA=J!@rb!O z#%ad6ltE+4#bmiTWUPoV;ag45+P;PYq zd?Syxcr=etY1di-J9|>5CAXS3ee_w#tL-Dqmm@XrQ%_*_haG;k8lb~y@i(rts1EyW z_>2zJ*j4 zHQK~3yY^~0l_LWA0ZMgY;lY8B-lKCHvymY$(o@k_fmNr?S3pU2DI43}mpAjhV0GoQ z3aSaQD(bh#sH^EppVt!7C3EmyF|EUo)IW`JJygt(;A2#=xz5*FAgHmWn84AF%&;Ryk1u)jE4ar*@a(Xm*yVBQWRYGUYk3 zO0HX}J7!GLojoB(ea=?rw`%+K_W+me#Z}w)@ukNXBs27GIYwWIyBpC&^|)A$*^;`t zG+f?dJY#Q#R)W+&X;}&RT zX2_uTff8L__PR5MQPOJ3?iHp?0G@0ucljyk&Bs2|H{^hx+@iGg?Bz;o7SFT)qIos{zf=C%iuqY!>2= z?q=!OTDScGC+oVs_HX0{f!@C*H#p{2_g5LuE|Z#x;)U2hVdWSTQdGbv(_b+|vg9)` zV6%1QsU#JJdtF&O3zK&6iM9Ee=pI=)p{Ao9&>f{6frq0zd&Q<94Za zT}M5KlNh)pQN|O%3!U_Z#kVr=EyR2Umd|9!ZhsiCaUskrhW{*nOY5i=bkZ-N!fK_# zpwn0$Y8iz?25pNv?wCZdO2Ny^yf3alu>Wx5fNl#lT1AIURx_Kuiu+nxS5YI-W7Iz5 zfI=2VWZGeulDcGe)0&xj>opR#!(vAnttF@=P+CT7Y@WfaoqV$p)~DpDhf_UVg^H(+#{4n6zhyK)p>sJTU$fy->6 z^)M09YM-cN2|enE3k))wtCNye$HU6Bo@a-EX}_zdLe&q#f+akW2~T{l(OGgPRi`gW zpgP;@Ai>2*rU}MMlrg9mjyfn0*JdP6KP@#=jdsbjwAU_bf_NyWXbA93POY`zF(jtL;;l>UP`%>I?V%qaRG3Pkjy#L)~5iREs+Q8R8 zy8~!rM*uPuPncUBeNg-tUNn8-+Tg*%rNthUfNe=M(_ErO@-Q_aG%Ouj$cZ@K086a- z(xvc}YMFj_tqF$o^PV1X-JoGbeIL)|$rr-*mB--NF}V)pVMRpR!N_~i)&M+?(xKDa zSXn`50m-F=(VWqjgW*GeSd{h zn@*E7%1b*C;^1oa=vaZ<0o3!bmoa)B=83Tz2T#S<*NX&?2{gY@K|m2Kbymguls{4KZK@jKXe`mjs8rGEjWa@z?)@aNSe>)|0y2<} zc_18bNCu`R3*H7LUTFFmb>j{c#}`Y@l?mq9$68}=(;a_|n9hakO~Agm46-g9Qdz#_ z&p1SpDcs{}KAQkJ!8SnHqFltx&nPZK`~`V8b6~srH^>bX4=h=|Y{mbeJ#&=nktk3e zG+#jhz(yawOs*7kp;c_H z-KAIDn50FkaP+lPbr2eFaCK}Re~&-@BR%?D=P?zD*t>&r|FqsOn&! zUc1xf3dxL((2`Y?5;|#(+Jfad`EyeBs|G|Mil-#C?hX^jgu&O;&){avCQwVUs;5_Q zlp_2xHJE?WZq3O6^Hw^ETR+|jZrq^}tSeDP^!B6}Tj1kpHTXo#Tr%}Evg(}1I$(J+ zDhqk2tY8s76d5*)uZVbVlYo4-i3Dpy49!%6uN;Xuc7O~i#zKy1Ap8ZYJ(3yN_NJQ9 zFkF7D1s#5K2tr%=KGsT*#|d&3!>Bwc*%B$wkdA8!LcGc1bZM9@_&Yf1R5p3L`3Ilj zHM}^oSLM#J)-U8Q2U|6wjS>liPn}a+il4nF33j_?dM;qTr=?UU0ftiU-{GnC(0IJD zQq(N`iQUq8iX3blbpEb2T@!!a<8HNXMCNuTuN0iRwY!hvL%}jRW8y{7T(MZQ+{=d6 z&vTAcUIp_NT~yS+!TkatII~{Jf-FrvrQnfl#o{u^bK90>u8~i#l!o)Wv0OJaecaGFY3Wc!)vibIcSH85fMgHsvSVb z;-`eZ)o!uN+ib+=k2?~ayZQE|mV!}a4iz3`Wxq^PXGUO&5dUcXaVk1*BD-25kZ>R< zvWpsFMMGuL`+BPUZnzX$VDTl$3jfq@{q{P~opl0f#&<9i?H%Q^%e=Td+;ft-s)v-O zL>n{9w=MCkdc+S-;9ep#5Pfg~eVP*w%!sz>z1p3)#i87{#PK!9+e`y7cK=sWVD+~w z^8W#cLee`F`pNs%6USV$Nj!P$Ogsm6l=K5jPNL*fq(`iX-M0Nin{_bSTFkIuh==9^ zb#f&7p~&_$$XJKOFv~SMD4MW3$ShBdof9B}$JdL@lF1<%3YezrxDu|P(J1a2RRZuW zKf2hV{?4+;hSzo^y3IG%g>MF>&)n>dyrZ!M^a_*U9S>#waT18=E{@e1ghHtHbmD-M zO`Vae4AZ~jq3jf#>)g)wz~B4yDZtczTN#_rt`glZx3Yw1dH%=gs)FpfCUw`=Dpl`} zcAvD~8mxM|WZ1a0>5AXx!|c^5EYgvi*OV;__tpHdrJ*Ym;a%r#dwz#vIW?F42Na7Y zEGF-(er;~=9)2~Vq=ZJO4KFN6JiT(Oh#qRbbScap)PJa9@#8 z=6gKS8Jug^p;XBU-R z6@nF8h5334Ey4MgB1!Y6z9uU{le%uZRh;ykrc4vv8b*My`bb`^&l?acj|D!G9h!)N z4C|)nG&4W7K>hz`lMrQW4-gdN#{i?7An0lk$Qj>^{E zhc@30n27XT@L8m0Un%(4`y)v>x^AT#j~^h1eZ5E^ot@q zh9@&B|4Aw}`k*x9%nNT5^jB^Kb&4Ej5tg9&)2~}Y_ROfE;6iFZm?%^F?zc4z{e zS#ygw+W6js>^4N76kJ}JF?wff4;s=$KjDL5E1zu6&6Q2&OE-`vFfw}G`mxgzL`GFq z)rAnCHR8ywN*a35zZJJOGg24dxMrav6Yr7QmkPD_L!z5Eyya*&yqN8HI=lYpLA-my z`-bhw5K44*0G=q2$U3R1m~HyRmj3QTeef044baM9UBY2Mj2$7mG&brsMnFH9$Cx|i zG^mWZR}AW3+|D0v_*}O4^fZ^iADDSBfViBRd%=FaOC<0vKi=^E?|1Y?+;7bk5q(a) z8&dMlx{MYyZoj>R4f{LO3u=m}1^m0cRs@VGyqM$Rj7QLbCY*zYaa^lCB0XX4XJ6(K(6oX?a^Xq(Oj@5@gn%g9tR zU_QeUnLW^VOT%rsdcf?SQ%Don2o*35J(F(#6ZJEug)rJHhQB1!_ ziTA1WdPOkV&!Q!RVfL5zlW89bTFcH}ipHlnt)ZBGlim0fYtg;OSn^utS+fsKOe2&p z8!wt@6}HqvJTiwL9&$;=19f+*e6(^mov+BcdBozg=GT>VLxP{ySSFl`EZL8P$6(^3 z{N)RGmNAIDg_~!doT`xcFhjyiz+6cwymETuP}}p3FFi84Yb44*JpY~R$V9}rW|H+R zpb3VTd~B;3nI%rm^%;eh9VkZkT;vhQ0OV58#5oRfMzVs59dknI7PBxgrHehPG+DP` zr$hddf~j~k3P@xx2kHeo34*jnq&-nc#_0NTPs6N1;tnQx^id(B=FmB>?X}9NX{r0l z@!onr-m6^8tuZGs5syyU`6cGEPMCu(%3e~ZeoU?L=xybyYkH_Qj{o;P8%mYtCRvy|yDtBym?m4ucA{FBSSXgm zhLKiEReTmzGj6?cv(HV6jC-af0BfJvi-k02J+t7FR)*k!jEM=ei-qq6Wb$tlw3j~{ zCzmHHGm=@}YIC38XSNT;eS`}HLhJB$mC$xXH%+SxZH$jx^L_Kqv5aIHL26S)=0W}!iW2xuon)Bqf(OUK!IfXLHsZEm*S4HthW=P zRBV!mzK81lp=HKcS1vXsFqZm@k}W2}=TjZ1SJQ+TYNqo~u!03Ii!M)UQdq9`@fk=4 zUJ+xnQW!7Aql}q&Fg5nD7k2MzkIezGjjMsvafEjzYBp6Kg9~^K zzrbEJI=yU@{I2xX9Tw{Nec=lLHoxxjf$KNXG_|e4$>5%p`EHuo+JV4HOOY3_8m1&U zvHU|rI+INLA4sM(-t;>@{0=)`v$>$r65E@!XwEe8#QeRHh)`_vQkQnRf|f)UJG3w>6b-4a$2uaKSx*lgYr?mN#V;(Z-$%$-g+Rzm8V7^Sbm8D2 z>}N~ladGXVg^E>!g_ye4a9Fy(E>`V=|P!{I`I$C8&A<)#1uJ;k%lohx# za|`0ZkJ{?o>l_5=YZcDfxMUqQFkv~H>F>zBS2H0~QpQ@WJCK`YAp8wkIfGo5thgp#H zN?iOo-XPL;QIo!()<}}?`iWdrTiR8Gdkwk+%=V|ht{ZOb+SLug!# z2g`G93A*(*=Bds)!mP4^gOXUiZW@B*o}gAFWcg^z23Pm+-Mv&9A1T}mT<(W3K+xhc* zYnj+#9(w;(*kHxL^D7Ql7Ye=oA?eE?u?y$^6#(KH+5$j4QQqG{Jp1&3&Ji;Il=?3AGzpzz4EYAY zuZlK(-$vDoL}S^GR@!{htDN?lDJFzTp0%YoG**5@$*S(m+$VybxnVL8Ztbd8ccTtV z0C<2DG3@cfIAW-vc;G3ZArRn25{~Jc=dPivV9V67yruR>b&?boU7q^U1uhAcw=ds-U5;;6HwD>tSL`?hLXlj@VT2^c85 zv#Io1IU8dq#M;fOWS1svG-crdd{&eKvEX1~pRL~eJ;~rv>6y?F3*RS~9FhZH*mQ+I z=0p1`@$|_G!^kFHs4@izk$4;C&*8_FZbhRWN6DtM*GyU#$0i(MRPA;X_|*&n3E%p5 zm4>0W9*-K<;t|8OOaNq-a@yE{nqfBDoUvK`mZ5qK{lRFBuMWqY##wnM)auU%5XGHK z^TjMo6qfpf2h<-bDC@T;zfCyz14%iRj*MMq*tXX6P4j;8A9vaS0PgwArwP>%b&Yu| zAn(UqJp*E*rnT~}r0d8(UI}q)tDIL|ZoffcC{KF$z;spWESAT72j?seQSHI~Z$EGT zH)8QO_I1?_`NL>frT?m3^TCI)`>@k8>cxAd`1Vc!E|+L-6pI?h zS2JoZ_m}Nl_nyg{v$YhliS4{E-=?($y1Ydu9_*L)F8bLMaQ-L8&FO;BBJF?4w;4Av z(ek&+QredTzF4K-49%bDZUPKaSepKcCI?Q@K1ea`PK~W~JsIN2>$y}lt`I#{>f5$9_hv5XKKIf4$B3#71L zD};{lggcVjg3E7evI3`PvS74|S)Bluw%m$|^vbkNq*Mc5#_F6E3H5v;YvuN#8DD9A z1Xq!_&y|Rc_5Cwb!c80GXMkiq*DTLp_V3DGIvmN{tz)qc^7Ik$@t`rR?as!lkC_qbr3D(wA&1y% zdhF2YYS25KN%QCChv61@>PwgB+mtic_%b-(bQ%8WL4k<=@)Sej3QwvuBebTpy+*QE z*1~{32X*O!z`_Gi%LNwTyK8Rcun$>K>ug2*mZ>6X*vu!7t+Y}@`r}Ok*&zS4PedlLwVVMhxx5KTc zYw<=UpYzq#wNn*pTeVpGz11B;m}&0q`hwP;=dOUFa}TWl<6z!zE zQtl{&yz}kKf9&Tn5VpSC;8Wiz0TXnJ)XlJ%x}BCEb`IcJyn@=K5M<(rg!wJ{l!o$_ zYjps#oW8FH{gv}KF3#=-ON~#x=@K5@0Junv($}c&6ye_|@&nu}J^1#LkN|Sqpnm)D zOneF>YQUpuc2$I(A+Figvrz;GS~hU0yPz#+MjY(Lu6J-7uc;KcWcwx`F(KF1OYX3Y zRYN3ZdRj`Y!T%+#9lokv&{4|;u`*R$Nt>0GR65Y|s$;1f-mmAT<=3^N@)f}Ip9vHK z;M`3qO6bBEFu(TfyMBfdQz=&{$dEBgwTy7LmNe;Q6Y@xo&t_UBR}tHxi``jt=Ejit zNAYAcb<>(c9Yh$vEO^KhYLe$a&8vpS_#tH26v-45feDWSGPF!|bJK8-ulU3S0OKOz z=kK-}fM?P0d0c-IqF0LGi%FeA|Fy!%!3_&GuRx1f7PtuWpz#Pq-$I_t3eNou5-$-s z9kDEYX1)(gf{jYTpQ1jNfNGuQ~}LW}eaqr}|yo>RYlMj3~#D@;xVVPiH9In2vZbx})jB<7%}> z959O3>7%uOJDIH{d;CQlko^~7_tfNecnDwgvZ_Y-j%Kg?VvyDCNgxX`+Fuh!lzVxT zJCyd#neE&g`@WLj^&Ji=?G@%Ppyk+8@6;`cW4Llpu=A%^tR?&m*9JEE%1hW!h<(u2 zz7%~wF|#*e2e@9x!`o8Q6Vo$XFM8F${TU_F9T<+b{+e{pZ`|}cA98{(ckHv0R1oOU z`+IGRJn21C_6<$Y^4CbP$E{eJ>NT6!A-Lv6qnbMJ7$RtOj@&Rhq7g_}JZ%${rz>S= z4Z`{-bQ~hg`HFJ&Tm#v;F`CoDbP#YY^V{KLCLbA_m_Jqac46;odf|Lzr1&f$W5_Ou zxzey~aYcY2urPCdfddw~m$Y{UC4x3S=l(hMAb#Q3W`O<=Cp={AJ}0oR4#2&4J=pkb zTlX!88VHbd;teA^QZ&0OuILJ#nUGW+DCFjHQ|Zeh=!eKhA`sONXtsU8t3{s%Pdx1* zIHr%nz3$iKdfXcU3b{z@u*!B5+B#*8$}Gn*!I76_m{cGE!uCfp|9jY;oNZYTjoM?% zEQOCAg4li|*VkVAtx!8~Q2N~$Q4O)}##|ux*_-d^eSZ>;*}qVe(}GmS?3k=bg7 zWj&toOV+;4QCzVP@3-bSEdm*9iuCf>%w-(ErWq4px7;7{kl#YVlcx%T`a@w8WtyAN z3f6Y&+r~SL{j>VLrwkHDnR@{9D8|Et43&GsdczVfve5F)YPt&5`MGi>WbNM+f<%yG3v(9|3i)BCjV-Ftm9o(5nub#4V6hC~R^3e3aX`+l!QPTnHfgMC; z*ZrMqJ^|vkKE8@^e)vH5Jld802J-9ZiwAq)vS|0OxH`IP0jLi(T{SV$wI0+yRQeSH z{d@Q5H&p)!r_~g-Kis1q#6LP>{(L{aJ5TEUzXAWa-(ma5FZ}e2{_!ifnh&7T`2Un= z_-@K76BeT#Xa#=0<_70po-wt$m1lUX=RSGu-S4@jHv41Gt@@U4692xo{m9Vk?~_DJ zcqSXDN0E66wSBkR401i7&0w4t;=BaY_Z|3q*6;x`(Kn)T--8m`Vhnr z1?BU`8xR#r8XC9@Dejx82en?*Qy=O94=G5vskcygM*c6gyiLh{Ezf-f)bfEf=7(4I zZ*LP-M`e->>e6?KD%-Z-6IH;TTVVr-P<6K|)`Y9E{oB&Cc z+|#5*&u2CMHD5e5BJ<^bew424zeyThh_viOlLDHyDtgU^p3wXbxQ5D}P&KD^o#3_TOJ)`!{*2z`!$H>$C&;XiQCXYraKR^Ov&9;g%Ps zq>BTd?dEB$G6p3&h(L@=d8}$}`3(X!16L4}3E^n<*V+XIaUuJ9^n|=ff3GseqQaF_ zz;~m%WXo%uXh5Bq$$&mkXV z<|K^$xat%)ovd;)>l;9%-h;SByo=8q7%3;}a)?SJZA8%xQC6=fxtWcIKdFItR?CtRl70H9-VKVa> zz%?o>hZhQmMUjZuZWn*pE=5;CKRO8KaD$hTQkWcs(Dt3R2tZN1_7Gd|_i2_OfHI~Z zZ#()B$yeVqVHhM>CL~C7rsT6mau>7@Mr=p6-|7R{rrs|U3pYAhOmJ^W#_ynfGY{S| za>!Go)htsc?NDh{Px@qPB1%lts%3+z8*5(i;PEF4~h&n)+9En4GrMUIjRe z7&3iGznRYjLN6jKe?ts|8o-^eO8PwF>y3&!GOm)%fU6xH7ZV()nVy94lqdIeKSN|J z0|+b#ZT@vpmA;WJEjKLFZraGXu^Xf@SN1rVUdSFDf>~S~5N|oThk%6GsdZa;XuEYC zG6H}3o;E0Tv;!@n7To7OdPQciWBy${h8uh3J?}a`aezn=x2*nmBaV_+FUF6x)`$l4 zN28wJB6z(JjGYQq=xjO_xu;$wBZcPLaK~;Qd?GPnfpoV-U-_AAo;O`(WlUVz2**+d zruAwkcFLYxLR`Fo?8_Dpus^y^O?ITKZh^`Sr|B>L;NeP7IFFVr@hU#!kPh#i!E_&h z(&@KD)XvtWZ=flNQc7K^lqe9{30XFBmh2ePgFO zepnoUM0P{8>CA^!-C+RTn)q-F!ogv72YZjqHHg#o9Mt4!BoE4g3kj3mWO(93PHN z^UlOHn;gr%U==P$DvMY3{a*gbQjw3pRgxWLn?$CZ{=zhK2{Hq|ol;Q#eJ9(8mDPf| za8Lguah^}wnjMSzr4*P{Tx3=L4qS{J($r`fwn-j&spthP2btM;2{JWI#vUP*u+gTN zcXzlXz(*G}{ImR+FIc`Uc{l9R*^(9gIZFL9*)tAPif|pk8C1>eO@S3!>eyc?4@p!o zAXuOOLp}=P@A6Ts&_D7~Yj}UkM+sKA@ZaX67}fu2K1$K(f6qrbhWs@j65-0z=syOY-iK`E~Esbo2`}uvhY+ zq4mjI#@}8b@PjeHcTCOvq5*1Q?(wfX&jXIXGY&O)t*CNJaU2n1|0-waO`nXx|9nF4 z`~92c?1zSgt?P!%lVswCj*LYYU){}C3};SPjRKm6`}f`lrssE-BQERPnl=xpY40pY z{a_3N6^+!Kud@QRpM3D3%7rxnbDmfwdd+juUEX%cp_*TDGxmMABEft_Jf{!{As#u-+$!6SpV1n3_O#`!J#4R9;hr=ylYu4OKt9N3VB&dXMOgg&dWo%x3H{GIs+1%Lj9Gq~kIvf@BZl>FAV?tRBfG;< zwrFu?nIWm=`xwzjR9m)mXq<_g)py5o>__f-l1{V*H;-SjKl|J#)|}Fq z8HY`5L78*u62<0+aq9HKA=%vX_^B4QiC%}<7X#P8gpH6CaxKKQ{GuqWILTcye11)@K)tP=JzU>i{X zDVl5M-AiBU+(sV@i*S{!-~(-$7Vg`@w&5aC3thhUYsk|>P`>kp^oNkM@`8liv9|1} z)}o#8>%pg8-P6G#HS6!po84#HlzX|0QZRaWMJ>Z5n!)3Y;yotIzs!W1AIW#H2yHtM z=8l$Z;MZV{j`ZtD8#3uN+B=S@7|R@BG0V}){zd&DdQqAk1;N{ z7?njUszz~l0v|i!fI>DV%Hke*BKhOH^wstNi00Toh7V5C4?kcg9BLDPajj2q<^)Ig zGM?)Rs{I|9;F5qJ029c*Sr1jY0~0t0h3=)R$vg?&O6d(cW{!Fh7Rxlw7XG(objgp+ zyFGTaO;}^kVc~VPqrfW<2>O}hqzPTWogIjcel!vdyi}6V`&+CR;+P2Ymu}y}iz1&1 z{b2UEDm;s?k+XT@kGX(}q}gDfq4j6i??Bz> zLVL-7Qzx6q+epH!2%;4`vg|sb*u)`;CO-uHKU>y>PcU65(GxM8eV0v9s4Rh`ig=K4 zxrk#z;L5OEFEw^vP2;jWp&^gp7&18uxfijMeR$DM(6N=kVu{73PJeV)RXqFCF@|t* zcgXubZeP1r9jtl*J9+tnD^T0f*v?3>^a^gNHcKvEz@iUgVR_~V`k8>N8_pO<%X@rO z_0Wy7!6HbyTOO(X%~ayX5bQVkn>a*7BL;u6T4<_{XerUc6z7(=KdA7 zb!}S?#E3abk$;KM2X!5Z& zEX!_Qx>b3ds%N0=>tI8%sVNdb$r#KV*B zpFp#|z@G-3PY~iE9s6=&O;R#$xKa#P#F8xOVL|#!SrC0fUYq(JE;HrB3x(A90$Ukc#qT0qqky8G(IC)D8U>g?Il@7<_np z2}QdGEzIG*F5W;D11JjiG($^G1m<8pp-ML*1)rUSmWo8dGXsB+#~R%VMde;m5XChv zir!js9{$!Oa7|pxHNBR*hMOyRH&v(0LYjxK_3Ez-*#f*y%$%jx+)Y9f37L&RevJVi zMfHv!iz2EFzaK=nY^F@lE=B7=rm@qw0XqxShC;r{+>oBuNWvYREz;8-t#RBS%S7^fG>jASvm% zMNtg*rJGztgz1;8malx2n|b>|DcZGB(sfXb8~h>$SYHoqf)NhAs@lFR%DgD9B&QVd z(&o#__6N4_B90uSB{^lQ&;i#K&>>6}SBKST!+Q%z^Vv##iY@2vl-b3Q`piTn5?S)j z=vYp06Gq-v(icIN?xE!1)*_Y8!W&|bO4)EZk@^}-4LMmOZibigAT0TQZ8q375~~C# zib&?r=l0re>l$5hu~n45bYZVk}_t0ttu)1y^GZ^a2(6czYQY( z6We3o@9WIOx0Cp^my|q8$6_dfN6Zpfq8@kHhMkn(unn1U^b9>IB?Ub@@5~!3bsfA5 zrCPwc+W-pM33JUY1&#Yg`+z?VIrJaa`t}dG&M~RM{IR3}6+WDGwM9wmeb|?4m1)+z zT$2}e49=jX-IC(&E|cr0%A}}GmBCi-bNP%6`2&GgZU*m}Gqk_a9_!b_%52wt{G;zU ziY-LTM*K#weszfJ=t5tpx`ac*B5B42z;RvCwCDae*p*VLc+8ehj6Z7t$D*!CnvI$((_j7d??qPCr>`SMqAczus-0{NKio_Gr%~q!)`o3d5 zfQ4$YQ$XvvO13*D2{1#y*pN{ESkD{HK=@_xj?_P6REiVVTw=N?xK3&^uTZHTvd?Bx2vqqmrL=El#WQg8@q22-U8crzaYcLJypq*DS!mVXk!OHV)0s{ zCj`{yhmQzg*;V!<-ov&$!CkUqvrTg{Lm_!JBUV5EJj$-yz?B?(V;Mpggu3tON3e0U z=>gz7zKYnN5GQV&vd>OLg!rE7@PY?9`tvo}B9vV7V|=ZD^Gq$?VlXnp|JaT2r8rjxYbKhyPA>{0K^;HTrdd
6`}+^xzOz5p0}snMy-4yi^xR2AGi#OK>I}8* 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%0AhqTZoz-5g|2s5%03KQo% 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 z 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 Vi3zRSmK|gO0#8>zmvv4FO#n=*HNyY^ literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/modified_arch_file.png b/docs/source/tutorials/arch_modeling/figures/modified_arch_file.png new file mode 100644 index 0000000000000000000000000000000000000000..520295c673ba4cd6a107b17001834169c44a47e2 GIT binary patch literal 106370 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 JeR}Hq{|j~rAuj*` literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.pdf b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.pdf new file mode 100644 index 000000000..5bdb9dc3a --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.pdf @@ -0,0 +1,100 @@ +%PDF-1.4 +%Ç쏢 +5 0 obj +<> +stream +xś­KŹG Çďý)ęHz?\"EHÜ #ĺČŠ]eHx‰ŻŹ«»\m»6°hłóźźŰîjŰĺ®÷Ć‚3¶˙ŤĎ›ëöäe1w·÷[qÖ¸dgb±Ö¤2„f>Ľ1w[2_6ožoJ2Ďľ…ożoÎ׾Lâşň˙lo‘)-­Ţ„ZÄÚ™ˇH®Ć.ăŠő=熢¸äČąˇHλj!gĆ‘˘¸čäÂąˇ(.ç‰ű%EqÍfHÂďP$ţ“¸_Rj„Ô87Ĺĺŕ!rż¤ś5wnĎ3>n®ć× ćHEď¸:sąÝzţřś|3Ź{•Šż$ĐOÄܸ\·Gö—ËßŰo—íĹĚö”1č›Ě„ěKŔWPrt'Ńa4‘ß1)Š ±ArśŠâR­xf‘˘¸ęŐ&ErÉ\ +î—Ĺá…87ĹĄ rż¤(®4ő„I‘\¶ŃBŕ~I9¸gAp5ŕÓiŞňžh˙îă’ +ě1c*Đ7™ +ř‹ĺń hŢGrż_RWRŔ; )ŠkmoaŚĘOX—ě{Ż +űşx±.­fh)âš—Đ=)˛Zl»/—ldŤµ•^ŤY7Mâšëw‚ś¶<¸i˝rC‘śďUî÷+8˛^9R—p‹g~%7­Wn(Š«>CmÜŻŕ¦őĘ ErÁb˘ŘÄý +Ž¬WŽŵ\ˇňu‘Ü´^ąˇHw˘–Ż‹äČzĺH‘\ꍴzćWrd˝r¤H.Űžöů•YŻ)Š+6â?ĚŻä¦őĘ ErŁĎhłQpǨă°qA)¬>IYëÓYŹĺďY}:„Á6ĹN5ăVÝü˙st˝•ŠäÎşÓ–ŇďĘÉş›Ü¬m©ü®ś¨âÎ:Ń–ŇďĘÉ:™Üľ§đuVYŻÜP—ě´Ąň»rC‘\Ś~lµÚRú]9R$wÖť¶”~WNÖÝäRöŔÝ*ŚŚě$u±˛“>WLÖđä|ňPxN)Ž¬Wn(ŠkaŚ[ÚRů]ąˇHnôm&{‡ÇöŁ8ëCą§w8\,Ç÷vçqĚ[ZÂĎŽp/E[0Ő6÷m(ť®ŘţĆş´“NL÷‚c˝@ +§+¦ZÁť©,ͤOM©D> –ČŇL8\)•Ć›;–˛S>LlY;sXJ§+&SýŔ(ÓĄ%zh­á€đě|ëďłnۇˇţšRNĺ0yŃçčqšĐŹđâý8!îŻ żígÇ‘D×öó…«ĺgXDăB#gőM÷1Ĺ®śu›‡ĽööGĐ°¸Ç`ź}ôÎ}MřFŇ/!',č>Ř_ţşľ™s˝…›w ÔŚ/E.› +‹=îßW ~â|ŐľeS?E;ß mG +ŘŻF´xĘé¶EÜt˘Ńľ~ęî ÖYúqÉ7=G +vŽI?l÷XlÁţůÔŢě~ěľěěą3XęË?!XĚ‘Z«ößĎź^ÝĽş»ýďî5 »˙}ŘĂŘendstream +endobj +6 0 obj +1124 +endobj +4 0 obj +<> +/Contents 5 0 R +>> +endobj +3 0 obj +<< /Type /Pages /Kids [ +4 0 R +] /Count 1 +>> +endobj +1 0 obj +<> +endobj +7 0 obj +<>endobj +9 0 obj +<> +endobj +10 0 obj +<> +endobj +8 0 obj +<> +endobj +11 0 obj +<>stream + + + + + +2021-03-30T21:42:15-06:00 +2021-03-30T21:42:15-06:00 +UnknownApplication + +Untitled + + + + + +endstream +endobj +2 0 obj +<>endobj +xref +0 12 +0000000000 65535 f +0000001448 00000 n +0000003096 00000 n +0000001389 00000 n +0000001229 00000 n +0000000015 00000 n +0000001209 00000 n +0000001513 00000 n +0000001613 00000 n +0000001554 00000 n +0000001583 00000 n +0000001675 00000 n +trailer +<< /Size 12 /Root 1 0 R /Info 2 0 R +/ID [<58720271AC737B87F98369E4524E3394><58720271AC737B87F98369E4524E3394>] +>> +startxref +3219 +%%EOF diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waves.png b/docs/source/tutorials/arch_modeling/figures/Custom_Waves.png new file mode 100644 index 0000000000000000000000000000000000000000..a669c2233e43c4c198d7c2cf426b2d96df34b9cf GIT binary patch literal 102893 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� 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 Date: Fri, 2 Apr 2021 14:22:03 -0600 Subject: [PATCH 081/352] Update tutorial to swap in PNGs and fix errors --- .../arch_modeling/open_cell_libraries_tutorial.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index bcea52c0c..11a15a447 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -6,7 +6,7 @@ Introduction **In this tutorial, we will** - Showcase how to create an architecture description based on standard cells, using OpenFPGA's circuit modeling language - - Use Skywater's Processor Development Kit (`PDK`_) cell library to create an OR Gate circuit model for OpenFPGA + - Use Skywater's Process Development Kit (`PDK`_) cell library to create an OR Gate circuit model for OpenFPGA - Verify that the standard cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave Through this example, we will show how to bind standard cell library files with OpenFPGA Architectures. @@ -14,7 +14,10 @@ Through this example, we will show how to bind standard cell library files with Create and Verify the OpenFPGA Circuit Model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In this tutorial, we focus on binding a 2-input **OR** gate from a standard cell library to a circuit model in OpenFPGA's architecture description file. Note that the approach can be generalized to any circuit model. For this tutorial, we start with an example where the HDL netlist of an 2-input **OR** gate that is auto-generated by OpenFPGA. After updating the architecture file, the auto-generated HDL netlist by OpenFPGA will directly instantiate a standard cell from the open-source Skywater 130nm PDK library. + +.. note:: In this tutorial, we focus on binding a 2-input **OR** gate from a standard cell library to a circuit model in OpenFPGA's architecture description file. Note that the approach can be generalized to any circuit model. + +For this tutorial, we start with an example where the HDL netlist of an 2-input **OR** gate that is auto-generated by OpenFPGA. After updating the architecture file, the auto-generated HDL netlist by OpenFPGA will directly instantiate a standard cell from the open-source Skywater 130nm PDK library. To follow along, go to the root directory of OpenFPGA and enter: .. code-block:: bash @@ -27,7 +30,7 @@ This will run a prebuilt task with OpenFPGA cell libraries. When the task is fin vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.v -.. note:: Users can find full details about netlist organization in our documentation: https://openfpga.readthedocs.io/en/master/manual/fpga_verilog/fabric_netlist/ +.. note:: Users can find full details about netlist organization in our documentation: :ref:``fabric_netlists`` The ``luts.v`` file represents a Look Up Table within the OpenFPGA architecture. The important lines of this file for the tutorial are highlighted below. These lines show the instantiation of OpenFPGA's **OR2** cell library. @@ -190,10 +193,11 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: -.. figure:: ./figures/Control_Waveforms3.svg +.. figure:: ./figures/Control_Waves.png :scale: 100% Control Circuit Model's Simulation Waveforms + .. note:: The waveform inputs do not need to exactly match because the testbench provides input in random intervals. @@ -462,7 +466,7 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: -.. figure:: ./figures/Custom_Waveforms2.svg +.. figure:: ./figures/Custom_Waves.png :scale: 100% Custom Circuit Model's Simulation Waveforms From 75891f800d398ec17cc3534be6b781339c2c67bb Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:24:51 -0600 Subject: [PATCH 082/352] Update to fix reference link and shrink PNGs --- .../arch_modeling/open_cell_libraries_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 11a15a447..1377b82b2 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -30,7 +30,7 @@ This will run a prebuilt task with OpenFPGA cell libraries. When the task is fin vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.v -.. note:: Users can find full details about netlist organization in our documentation: :ref:``fabric_netlists`` +.. note:: Users can find full details about netlist organization in our documentation: :ref:`fabric_netlists` The ``luts.v`` file represents a Look Up Table within the OpenFPGA architecture. The important lines of this file for the tutorial are highlighted below. These lines show the instantiation of OpenFPGA's **OR2** cell library. @@ -194,7 +194,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: .. figure:: ./figures/Control_Waves.png - :scale: 100% + :scale: 75% Control Circuit Model's Simulation Waveforms @@ -467,7 +467,7 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: .. figure:: ./figures/Custom_Waves.png - :scale: 100% + :scale: 75% Custom Circuit Model's Simulation Waveforms From 15fcf03e31aed9a48ecb43740f085e81f8ec8ca2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:42:23 -0600 Subject: [PATCH 083/352] Crop GTKWaveforms --- .../arch_modeling/figures/Control_Waves2.png | Bin 0 -> 38137 bytes .../arch_modeling/figures/Custom_Waves2.png | Bin 0 -> 37344 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waves2.png create mode 100644 docs/source/tutorials/arch_modeling/figures/Custom_Waves2.png diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waves2.png b/docs/source/tutorials/arch_modeling/figures/Control_Waves2.png new file mode 100644 index 0000000000000000000000000000000000000000..646bdd186c2ab9c4a8eedbf1a3557a01429242cb GIT binary patch literal 38137 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 Q90L$|y85}Sb4q9e01L{I+yDRo literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waves2.png b/docs/source/tutorials/arch_modeling/figures/Custom_Waves2.png new file mode 100644 index 0000000000000000000000000000000000000000..cf84a67845ede07199590d784deccc8facbb7a67 GIT binary patch literal 37344 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 literal 0 HcmV?d00001 From dc725dfd6f1f735401cee604f6d0aa414303cc81 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:43:37 -0600 Subject: [PATCH 084/352] Update to use cropped GTKWave PNGs --- .../arch_modeling/open_cell_libraries_tutorial.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 1377b82b2..38a519b17 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -193,8 +193,8 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: -.. figure:: ./figures/Control_Waves.png - :scale: 75% +.. figure:: ./figures/Control_Waves2.png + :scale: 100% Control Circuit Model's Simulation Waveforms @@ -466,8 +466,8 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: -.. figure:: ./figures/Custom_Waves.png - :scale: 75% +.. figure:: ./figures/Custom_Waves2.png + :scale: 100% Custom Circuit Model's Simulation Waveforms From 0655cda94d7865fc7837c7637c27300bfca3850c Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:45:47 -0600 Subject: [PATCH 085/352] Rescale PNG images downward --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 38a519b17..fa1586ee1 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -194,7 +194,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: .. figure:: ./figures/Control_Waves2.png - :scale: 100% + :scale: 75% Control Circuit Model's Simulation Waveforms @@ -467,7 +467,7 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: .. figure:: ./figures/Custom_Waves2.png - :scale: 100% + :scale: 75% Custom Circuit Model's Simulation Waveforms From d5ec17867d8223aa411e93215752ce8cee679c33 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:49:58 -0600 Subject: [PATCH 086/352] Add files via upload --- .../arch_modeling/figures/Control_Waves2.png | Bin 38137 -> 14516 bytes .../arch_modeling/figures/Custom_Waves2.png | Bin 37344 -> 13170 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waves2.png b/docs/source/tutorials/arch_modeling/figures/Control_Waves2.png index 646bdd186c2ab9c4a8eedbf1a3557a01429242cb..1fd0ac6c5668d4ab35bdd88da01cdcf3d00b8548 100644 GIT binary patch literal 14516 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 Q90L$|y85}Sb4q9e01L{I+yDRo diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waves2.png b/docs/source/tutorials/arch_modeling/figures/Custom_Waves2.png index cf84a67845ede07199590d784deccc8facbb7a67..85b701dda39baa155d1274a7a06cdaa85e05f2d1 100644 GIT binary patch literal 13170 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 XPcM`PwmAL$H45yZhGM?_)1dzk$qt)A literal 37344 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 From b4945a3c1eb0c3b975277c023e688a040aabc654 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 15:56:56 -0600 Subject: [PATCH 087/352] Update to change information errors --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index fa1586ee1..582e14b0f 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -6,7 +6,7 @@ Introduction **In this tutorial, we will** - Showcase how to create an architecture description based on standard cells, using OpenFPGA's circuit modeling language - - Use Skywater's Process Development Kit (`PDK`_) cell library to create an OR Gate circuit model for OpenFPGA + - Use Skywater's Process Design Kit (`PDK`_) cell library to create an OR Gate circuit model for OpenFPGA - Verify that the standard cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave Through this example, we will show how to bind standard cell library files with OpenFPGA Architectures. @@ -205,7 +205,7 @@ We have now finished creating the control and viewing the important sections for Clone Skywater PDK into OpenFPGA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We will be using the open-source Skywater Processor Development Kit to aid us in creating our circuit model. We start by cloning the Skywater PDK github repository into the OpenFPGA root directory. +We will be using the open-source Skywater PDK to aid us in creating our circuit model. We start by cloning the Skywater PDK github repository into the OpenFPGA root directory. Run the following command in the root directory of OpenFPGA: .. code-block:: bash From 1534a3a7c71dc7761207098214207ae85bf9db6c Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 16:02:41 -0600 Subject: [PATCH 088/352] Update Figure Citations --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 582e14b0f..5580ccced 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -196,7 +196,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. figure:: ./figures/Control_Waves2.png :scale: 75% - Control Circuit Model's Simulation Waveforms + Simulation Waveforms with OpenFPGA Circuit Model .. note:: The waveform inputs do not need to exactly match because the testbench provides input in random intervals. @@ -469,7 +469,7 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. figure:: ./figures/Custom_Waves2.png :scale: 75% - Custom Circuit Model's Simulation Waveforms + Simulation Waveforms with Skywater PDK Circuit Model We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please reach out to us. From 69c96938c0ec6da13a4347e26d35330bbd8c9ad6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 5 Apr 2021 11:37:43 -0600 Subject: [PATCH 089/352] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e71c1f637..9a9238b94 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,14 @@ The award-winning OpenFPGA framework is the **first open-source FPGA IP generato **If this is the first time you learn OpenFPGA, we strongly recommend you to watch the [introduction video about OpenFPGA](https://youtu.be/ocODUGcYGqo)** -A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools/). -We also recommend potential users to checkout the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights.html) before compiling. +A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/getting_started/tools/). +We also recommend potential users to checkout the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights/#) before compiling. ## Compilation **A tutorial video about how-to-compile can be found [here](https://youtu.be/F9sMRmDewM0)** -Before start, we strongly recommend you to read the required dependencies at [**compilation guidelines**](https://openfpga.readthedocs.io/en/master/tutorials/compile). +Before start, we strongly recommend you to read the required dependencies at [**compilation guidelines**](https://openfpga.readthedocs.io/en/master/tutorials/getting_started/compile/). It also includes detailed information about docker image. --- @@ -55,4 +55,4 @@ OpenFPGA's [full documentation](https://openfpga.readthedocs.io/en/master/) incl ## Tutorials -You can find some tutorials in the [**./tutorials**](./docs/source/tutorials/) folder. This will help you get more familiar with the tool and use OpenFPGA under different configurations. +You can find a set of [tutorials](https://openfpga.readthedocs.io/en/master/tutorials/), with which you get familiar with the tool and use OpenFPGA in various purposes. From 1d97cbf9b25fae63e187057b74ac2d77e90370ea Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 9 Apr 2021 08:38:20 -0600 Subject: [PATCH 090/352] Update to improve readability --- .../arch_modeling/open_cell_libraries_tutorial.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 5580ccced..6a1e3fda0 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -205,7 +205,7 @@ We have now finished creating the control and viewing the important sections for Clone Skywater PDK into OpenFPGA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We will be using the open-source Skywater PDK to aid us in creating our circuit model. We start by cloning the Skywater PDK github repository into the OpenFPGA root directory. +We will be using the open-source Skywater PDK to create our circuit model. We start by cloning the Skywater PDK github repository into the OpenFPGA root directory. Run the following command in the root directory of OpenFPGA: .. code-block:: bash @@ -223,15 +223,15 @@ This will take some time to complete due to the size of the libraries. Once the Create and Verify the Standard Cell Library Circuit Model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To create the circuit model, we will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` OpenFPGA architecture file. We will remove the circuit model -for OpenFPGA's **OR2** gate, replace the circuit model with one referencing the Skywater cell library, and modify the LUT that references the old **OR2** +To create the circuit model, we will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` OpenFPGA architecture file by removing the circuit model +for OpenFPGA's **OR2** gate, replacing the circuit model with one referencing the Skywater cell library, and modifying the LUT that references the old **OR2** circuit model to reference our new circuit model. We begin by running the following command in the root directory: .. code-block:: bash vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml -We begin the circuit model creation process by replacing **LINE67** to **LINE81** with the following: +We continue the circuit model creation process by replacing **LINE67** to **LINE81** with the following: .. code-block:: xml @@ -299,7 +299,7 @@ directory, run the following commands: vvp compiled_and2 -With IVerilog complete, we can verify the cell library has been bound correctly by viewing the ``luts.v`` file and the waveforms with GTKWave. +With IVerilog complete, we can verify that the cell library has been bound correctly by viewing the ``luts.v`` file and the waveforms with GTKWave. From the root directory, view the ``luts.v`` file with this command: @@ -471,10 +471,12 @@ The simulation waveforms should look similar to the following :numref:`fig_custo Simulation Waveforms with Skywater PDK Circuit Model -We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please reach out to us. +We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please `contact`_ us. .. _Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ .. _PDK: https://github.com/google/skywater-pdk .. _GTKWave: https://github.com/gtkwave/gtkwave + +.. _contact: https://openfpga.readthedocs.io/en/master/contact/ From c6ae2a9b171334199a96069dfb241d5c2d01e5d4 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 9 Apr 2021 09:15:25 -0600 Subject: [PATCH 091/352] Fix opening paragraph --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 6a1e3fda0..e7d232ca3 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -17,7 +17,7 @@ Create and Verify the OpenFPGA Circuit Model .. note:: In this tutorial, we focus on binding a 2-input **OR** gate from a standard cell library to a circuit model in OpenFPGA's architecture description file. Note that the approach can be generalized to any circuit model. -For this tutorial, we start with an example where the HDL netlist of an 2-input **OR** gate that is auto-generated by OpenFPGA. After updating the architecture file, the auto-generated HDL netlist by OpenFPGA will directly instantiate a standard cell from the open-source Skywater 130nm PDK library. +For this tutorial, we start with an example where the HDL netlist of an 2-input **OR** gate that is auto-generated by OpenFPGA. After updating the architecture file, the auto-generated HDL netlist created by OpenFPGA will directly instantiate a standard cell from the open-source Skywater 130nm PDK library. To follow along, go to the root directory of OpenFPGA and enter: .. code-block:: bash From 456a5538841f6e5dca957e0f570ede10ab3d5cca Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:02:37 -0600 Subject: [PATCH 092/352] Add Spypads tutorial --- .../arch_modeling/Spypads_tutorial.rst | 318 ++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/Spypads_tutorial.rst diff --git a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst new file mode 100644 index 000000000..08c3b2e0d --- /dev/null +++ b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst @@ -0,0 +1,318 @@ +Creating Spypads Using XML Syntax +================================= + +Introduction +~~~~~~~~~~~~ + +**In this tutorial, we will** + - Show the XML Syntax for Global Outputs + - Showcase an example with Spypads + - Modify an existing architecture to incorporate Spypads + - Verify correctness through GTKWave + +Through this tutorial, we will show how to create Spypads in OpenFPGA + +Spypads are physical output pins on a FPGA chip through which you can read out internal signals when doing silicon-level debugging. The XML syntax for spypads and other +global signals can be found on our :ref:`circuit_library` documentation page. + +To create a spypad, the ``port type`` needs to be set to **output** and ``is_global`` and ``is_io`` need to be set to **true**: + +.. code-block:: XML + + +When the port is syntactically correct, the outputs are independently wired from different instances to separated FPGA outputs and would physically look like + :numref:`fig_gpout`: + +.. _fig_gpout: + +.. figure:: ./figures/gpout_ports.png + :scale: 100% + + Diagram for General Purpose Output + +.. note:: The general-purpose outputs are not applicable to routing multiplexer outputs + +Pre-Built Spypads +~~~~~~~~~~~~~~~~~ + +An OpenFPGA architecture file that contains spypads and has a task that references it is the ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml`` +file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml`` by entering the following command at the root directory of OpenFPGA: + +.. code-block:: bash + emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml + +The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172** + +.. code-block:: XML + :emphasize-lines: 10, 11, 12 + + + + + + + + + + + + + + + + + +The spypads are instantiated in the top-level verilog module ``fpga_top.v``. ``fpga_top.v`` is automatically generated when we run our task from the OpenFPGA root +directory. However, we need to modify the task configuration file to run the **full testbench** instead of the **formal testbench** to view the spypads' waveforms in +GTKWave. + +.. note:: To read about the differences between the **formal testbench** and the **full testbench**, please visit our page on testbenches: :ref:`testbench`. + +To open the task configuration file, run this command from the root directory of OpenFPGA: + +.. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/config/task.conf + +The last line of the task configuration file (**LINE44**) sets the **formal testbench** to be the desired testbench. To use the **full testbench**, comment out **LINE44**. +The file will look like this when finished: + +.. code-block:: python + :linenos: + :emphasize-lines: 44 + + # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + # Configuration file for running experiments + # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + # timeout_each_job : FPGA Task script splits fpga flow into multiple jobs + # Each job execute fpga_flow script on combination of architecture & benchmark + # timeout_each_job is timeout for each job + # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + [GENERAL] + run_engine=openfpga_shell + power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml + power_analysis = true + spice_output=false + verilog_output=true + timeout_each_job = 20*60 + fpga_flow=vpr_blif + + [OpenFPGA_SHELL] + openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_script.openfpga + openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml + openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + + [ARCHITECTURES] + arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm.xml + + [BENCHMARKS] + bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + # Cannot pass automatically. Need change in .v file to match ports + # When passed, we can replace the and2 benchmark + #bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/test_mode_low/test_mode_low.blif + + [SYNTHESIS_PARAM] + bench0_top = and2 + bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act + bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + + #bench0_top = test_mode_low + #bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/test_mode_low/test_mode_low.act + #bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/test_mode_low/test_mode_low.v + bench0_chan_width = 300 + + [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] + end_flow_with_test= + #vpr_fpga_verilog_formal_verification_top_netlist= + +Our OpenFPGA task will now run the full testbench. We run the task with the following command from the root directory of OpenFPGA: + +.. code-block:: bash + python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/spypad --debug --show_thread_logs + +.. note:: Python 3.8 or later is required to run this task + +We can now see the instantiation of these spypads in ``fpga_top.v`` and ``luts.v``. We will start by viewing ``luts.v`` with the following command: + +.. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.verilog + +The spypads are coming from the ``frac_lut6_spypad`` circuit model. In ``luts.v``, the ``frac_lut6_spypad`` module is defined around **LINE150** and looks as follows: + +.. code-block:: verilog + module frac_lut6_spypad(in, + sram, + sram_inv, + mode, + mode_inv, + lut4_out, + lut5_out, + lut6_out); + //----- INPUT PORTS ----- + input [0:5] in; + //----- INPUT PORTS ----- + input [0:63] sram; + //----- INPUT PORTS ----- + input [0:63] sram_inv; + //----- INPUT PORTS ----- + input [0:1] mode; + //----- INPUT PORTS ----- + input [0:1] mode_inv; + //----- OUTPUT PORTS ----- + output [0:3] lut4_out; + //----- OUTPUT PORTS ----- + output [0:1] lut5_out; + //----- OUTPUT PORTS ----- + output [0:0] lut6_out; + +The ``fpga_top.v`` file has some similarities. We can view the ``fpga_top.v`` file by running the following command: + +.. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/fpga_top.v + +If we look at the module definition and ports of ``fpga_top.v`` we should see the following: + +..code-block:: verilog + module fpga_top(pReset, + prog_clk, + TESTEN, + set, + reset, + clk, + gfpga_pad_frac_lut6_spypad_lut4_out, + gfpga_pad_frac_lut6_spypad_lut5_out, + gfpga_pad_frac_lut6_spypad_lut6_out, + gfpga_pad_GPIO_PAD, + ccff_head, + ccff_tail); + //----- GLOBAL PORTS ----- + input [0:0] pReset; + //----- GLOBAL PORTS ----- + input [0:0] prog_clk; + //----- GLOBAL PORTS ----- + input [0:0] TESTEN; + //----- GLOBAL PORTS ----- + input [0:0] set; + //----- GLOBAL PORTS ----- + input [0:0] reset; + //----- GLOBAL PORTS ----- + input [0:0] clk; + //----- GPOUT PORTS ----- + output [0:3] gfpga_pad_frac_lut6_spypad_lut4_out; + //----- GPOUT PORTS ----- + output [0:1] gfpga_pad_frac_lut6_spypad_lut5_out; + //----- GPOUT PORTS ----- + output [0:0] gfpga_pad_frac_lut6_spypad_lut6_out; + //----- GPIO PORTS ----- + inout [0:7] gfpga_pad_GPIO_PAD; + //----- INPUT PORTS ----- + input [0:0] ccff_head; + //----- OUTPUT PORTS ----- + output [0:0] ccff_tail; + +Using :numref:`fig_gpout` as a guide, we can relate our task like :numref:`fig_gpout_example` + +.. _fig_gpout: + +.. figure:: ./figures/gpout_ports_example.png + :scale: 100% + + Diagram for ``lut6_out`` + + +We can view testbench waveforms with GTKWave by running the following command from the root directory: + +.. code-block:: bash + gtkwave openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & + +.. note::Information on GTKWave can be found on our documentation page located here: :ref:`verilog2verification` + +The waveforms will appear similar to :numref:`fig_spypad_waves` + +.. _fig_spypad_waves: + +.. figure:: ./figures/spypad_waveforms.png + :scale: 100% + + Spypad Waveforms + +Building Spypads +~~~~~~~~~~~~~~~~ + +We will modify the``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file found in OpenFPGA to expose the **sumout** output from the **ADDF** module. We can start modifying +the file by running the following command: + +.. code-block:: bash + emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml + +Replace **LINE214** with the following: + +.. code-block:: xml + + +**sumout** is now a global output. **sumout** will show up in the ``fpga_top.v`` file and will have waveforms in GTKWave if we run the **full testbench**. To run the +**full testbench**, we have to modify the ``hard_adder`` configuration file: + +.. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf + +Comment out the last line of the file to run the **full testbench**: + +.. code-block:: python + #vpr_fpga_verilog_formal_verification_top_netlist= + +We now run the task to see our changes: + +.. code-block:: bash + python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs + +We can view the global ports in ``fpga_top.v`` by running the following command: + +.. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/adder/hard_adder/run064/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/fpga_top.v + +The ``fpga_top.v`` should have the following in its module definition: + +.. code-block:: verilog + module fpga_top(pReset, + prog_clk, + set, + reset, + clk, + gfpga_pad_ADDF_sumout, + gfpga_pad_GPIO_PAD, + ccff_head, + ccff_tail); + //----- GLOBAL PORTS ----- + input [0:0] pReset; + //----- GLOBAL PORTS ----- + input [0:0] prog_clk; + //----- GLOBAL PORTS ----- + input [0:0] set; + //----- GLOBAL PORTS ----- + input [0:0] reset; + //----- GLOBAL PORTS ----- + input [0:0] clk; + //----- GPOUT PORTS ----- + output [0:19] gfpga_pad_ADDF_sumout; + +We can view the waveform by running GTKWave: + +.. code-block:: bash + gtkwave openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & + +The waveform should have some changes to its value. An example of what it may look like is displayed in :numref:`fig_spy_adder` + +.. _fig_spy_adder: + +.. figure:: ./figures/spyadder_waveform.png + :scale: 100% + + Sumout Waveform + +Conclusion +~~~~~~~~~~ + +In this tutorial, we have shown how to build spypads into OpenFPGA Architectures using XML Syntax. If you have any issues, feel free to `contact`_ us. + +.. _contact: https://openfpga.readthedocs.io/en/master/contact/ \ No newline at end of file From ce2e9c177b609cadeb7c9cfd0c7533ff918713be Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:03:41 -0600 Subject: [PATCH 093/352] Add figures for spypads tutorial --- .../arch_modeling/figures/gpout_ports.png | Bin 0 -> 16042 bytes .../figures/gpout_ports_example.png | Bin 0 -> 19860 bytes .../arch_modeling/figures/spyadder_waveform.png | Bin 0 -> 13439 bytes .../arch_modeling/figures/spypad_waveforms.png | Bin 0 -> 24078 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/tutorials/arch_modeling/figures/gpout_ports.png create mode 100644 docs/source/tutorials/arch_modeling/figures/gpout_ports_example.png create mode 100644 docs/source/tutorials/arch_modeling/figures/spyadder_waveform.png create mode 100644 docs/source/tutorials/arch_modeling/figures/spypad_waveforms.png diff --git a/docs/source/tutorials/arch_modeling/figures/gpout_ports.png b/docs/source/tutorials/arch_modeling/figures/gpout_ports.png new file mode 100644 index 0000000000000000000000000000000000000000..76b24955a5b87de9ef011975ca7f0d894c446805 GIT binary patch literal 16042 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 literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/gpout_ports_example.png b/docs/source/tutorials/arch_modeling/figures/gpout_ports_example.png new file mode 100644 index 0000000000000000000000000000000000000000..a862d336545a6d2822cdffbd22a6287673929196 GIT binary patch literal 19860 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 literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/spyadder_waveform.png b/docs/source/tutorials/arch_modeling/figures/spyadder_waveform.png new file mode 100644 index 0000000000000000000000000000000000000000..54e34a0017aca99e753ae12fdfae1b6b92b48285 GIT binary patch literal 13439 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 literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/arch_modeling/figures/spypad_waveforms.png b/docs/source/tutorials/arch_modeling/figures/spypad_waveforms.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea110f599f9cf9f40dc908f6fbaa21f0febf7b2 GIT binary patch literal 24078 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 z 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 Date: Fri, 9 Apr 2021 16:04:37 -0600 Subject: [PATCH 094/352] Update to include spypads tutorial --- docs/source/tutorials/arch_modeling/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/tutorials/arch_modeling/index.rst b/docs/source/tutorials/arch_modeling/index.rst index c7f53ef3d..b6c27e69e 100644 --- a/docs/source/tutorials/arch_modeling/index.rst +++ b/docs/source/tutorials/arch_modeling/index.rst @@ -10,3 +10,4 @@ Architecture Modeling quick_start user_defined_temp_tutorial open_cell_libraries_tutorial + Spypads_tutorial From 62da6b467dd346fd35b3b18dca1117402d7e8b22 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:15:44 -0600 Subject: [PATCH 095/352] Update tutorial to correctly display code --- .../arch_modeling/Spypads_tutorial.rst | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst index 08c3b2e0d..4b426e20c 100644 --- a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst @@ -10,18 +10,18 @@ Introduction - Modify an existing architecture to incorporate Spypads - Verify correctness through GTKWave -Through this tutorial, we will show how to create Spypads in OpenFPGA +Through this tutorial, we will show how to create Spypads in OpenFPGA. Spypads are physical output pins on a FPGA chip through which you can read out internal signals when doing silicon-level debugging. The XML syntax for spypads and other global signals can be found on our :ref:`circuit_library` documentation page. To create a spypad, the ``port type`` needs to be set to **output** and ``is_global`` and ``is_io`` need to be set to **true**: -.. code-block:: XML +.. code-block:: xml + -When the port is syntactically correct, the outputs are independently wired from different instances to separated FPGA outputs and would physically look like - :numref:`fig_gpout`: +When the port is syntactically correct, the outputs are independently wired from different instances to separated FPGA outputs and would physically look like :numref:`fig_gpout`: .. _fig_gpout: @@ -39,13 +39,14 @@ An OpenFPGA architecture file that contains spypads and has a task that referenc file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml`` by entering the following command at the root directory of OpenFPGA: .. code-block:: bash + emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172** -.. code-block:: XML +.. code-block:: xml :emphasize-lines: 10, 11, 12 - + @@ -60,7 +61,7 @@ The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac - + The spypads are instantiated in the top-level verilog module ``fpga_top.v``. ``fpga_top.v`` is automatically generated when we run our task from the OpenFPGA root directory. However, we need to modify the task configuration file to run the **full testbench** instead of the **formal testbench** to view the spypads' waveforms in @@ -71,6 +72,7 @@ GTKWave. To open the task configuration file, run this command from the root directory of OpenFPGA: .. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/config/task.conf The last line of the task configuration file (**LINE44**) sets the **formal testbench** to be the desired testbench. To use the **full testbench**, comment out **LINE44**. @@ -128,6 +130,7 @@ The file will look like this when finished: Our OpenFPGA task will now run the full testbench. We run the task with the following command from the root directory of OpenFPGA: .. code-block:: bash + python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/spypad --debug --show_thread_logs .. note:: Python 3.8 or later is required to run this task @@ -135,11 +138,13 @@ Our OpenFPGA task will now run the full testbench. We run the task with the foll We can now see the instantiation of these spypads in ``fpga_top.v`` and ``luts.v``. We will start by viewing ``luts.v`` with the following command: .. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.verilog The spypads are coming from the ``frac_lut6_spypad`` circuit model. In ``luts.v``, the ``frac_lut6_spypad`` module is defined around **LINE150** and looks as follows: .. code-block:: verilog + module frac_lut6_spypad(in, sram, sram_inv, @@ -168,11 +173,13 @@ The spypads are coming from the ``frac_lut6_spypad`` circuit model. In ``luts.v` The ``fpga_top.v`` file has some similarities. We can view the ``fpga_top.v`` file by running the following command: .. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/fpga_top.v If we look at the module definition and ports of ``fpga_top.v`` we should see the following: -..code-block:: verilog +.. code-block:: verilog + module fpga_top(pReset, prog_clk, TESTEN, @@ -223,6 +230,7 @@ Using :numref:`fig_gpout` as a guide, we can relate our task like :numref:`fig_g We can view testbench waveforms with GTKWave by running the following command from the root directory: .. code-block:: bash + gtkwave openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & .. note::Information on GTKWave can be found on our documentation page located here: :ref:`verilog2verification` @@ -243,37 +251,44 @@ We will modify the``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file found in Op the file by running the following command: .. code-block:: bash + emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml Replace **LINE214** with the following: .. code-block:: xml + **sumout** is now a global output. **sumout** will show up in the ``fpga_top.v`` file and will have waveforms in GTKWave if we run the **full testbench**. To run the **full testbench**, we have to modify the ``hard_adder`` configuration file: .. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf Comment out the last line of the file to run the **full testbench**: .. code-block:: python + #vpr_fpga_verilog_formal_verification_top_netlist= We now run the task to see our changes: .. code-block:: bash + python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs We can view the global ports in ``fpga_top.v`` by running the following command: .. code-block:: bash + emacs openfpga_flow/tasks/fpga_verilog/adder/hard_adder/run064/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/fpga_top.v The ``fpga_top.v`` should have the following in its module definition: .. code-block:: verilog + module fpga_top(pReset, prog_clk, set, @@ -299,6 +314,7 @@ The ``fpga_top.v`` should have the following in its module definition: We can view the waveform by running GTKWave: .. code-block:: bash + gtkwave openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & The waveform should have some changes to its value. An example of what it may look like is displayed in :numref:`fig_spy_adder` @@ -315,4 +331,4 @@ Conclusion In this tutorial, we have shown how to build spypads into OpenFPGA Architectures using XML Syntax. If you have any issues, feel free to `contact`_ us. -.. _contact: https://openfpga.readthedocs.io/en/master/contact/ \ No newline at end of file +.. _contact: https://openfpga.readthedocs.io/en/master/contact/ From afa0e751da57e7d85e43501ff12ff0c250a35ea8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Apr 2021 14:12:02 -0600 Subject: [PATCH 096/352] [Tool] Use alias for complex bitstream data types --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 4 ++-- openfpga/src/utils/fabric_bitstream_utils.cpp | 12 ++++++------ openfpga/src/utils/fabric_bitstream_utils.h | 9 ++++++--- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 828779ec6..13771bf28 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1602,7 +1602,7 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, fp << std::endl; /* Reorganize the fabric bitstream by the same address across regions */ - std::map, std::vector> fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); for (const auto& addr_din_pair : fabric_bits_by_addr) { /* When fast configuration is enabled, @@ -1711,7 +1711,7 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp, fp << std::endl; /* Reorganize the fabric bitstream by the same address across regions */ - std::map> fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); for (const auto& addr_din_pair : fabric_bits_by_addr) { /* When fast configuration is enabled, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index b1beeb00d..0dd4d4ed3 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -78,8 +78,8 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const Fabric * * Note: the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ -std::map> build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { - std::map> fabric_bits_by_addr; +FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { + FrameFabricBitstream fabric_bits_by_addr; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { /* Create string for address */ @@ -129,7 +129,7 @@ std::map> build_frame_based_fabric_bitstream_by_a *******************************************************************/ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip) { - std::map> fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); size_t num_bits = 0; @@ -161,8 +161,8 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit * * Note: the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ -std::map, std::vector> build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { - std::map, std::vector> fabric_bits_by_addr; +MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { + MemoryBankFabricBitstream fabric_bits_by_addr; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { /* Create string for BL address */ @@ -217,7 +217,7 @@ std::map, std::vector> build_memory_ba *******************************************************************/ size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip) { - std::map, std::vector> fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); size_t num_bits = 0; diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index e34464a89..1ad04dc39 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -24,13 +24,16 @@ size_t find_fabric_regional_bitstream_max_size(const FabricBitstream& fabric_bit size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const FabricBitstream& fabric_bitstream, const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip); - -std::map> build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); +/* Alias to a specific organization of bitstreams for frame-based configuration protocol */ +typedef std::map> FrameFabricBitstream; +FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); -std::map, std::vector> build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); +/* Alias to a specific organization of bitstreams for memory bank configuration protocol */ +typedef std::map, std::vector> MemoryBankFabricBitstream; +MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); From 4b8f5f294a40d45043e0606497e1094156a2b484 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Apr 2021 14:28:31 -0600 Subject: [PATCH 097/352] [Tool] Capsulate fabric bitstream organization for configuration chain --- .../fpga_verilog/verilog_top_testbench.cpp | 19 +--------- openfpga/src/utils/fabric_bitstream_utils.cpp | 37 +++++++++++++++++++ openfpga/src/utils/fabric_bitstream_utils.h | 6 +++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 13771bf28..08b7cd2e8 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1484,24 +1484,7 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp, VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); /* Reorganize the regional bitstreams to be the same size */ - std::vector> regional_bitstreams; - regional_bitstreams.reserve(fabric_bitstream.regions().size()); - for (const FabricBitRegionId& region : fabric_bitstream.regions()) { - std::vector curr_regional_bitstream; - curr_regional_bitstream.resize(regional_bitstream_max_size, false); - /* Starting index should consider the offset between the current bitstream size and - * the maximum size of regional bitstream - */ - size_t offset = regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); - for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - curr_regional_bitstream[offset] = bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); - offset++; - } - VTR_ASSERT(offset == regional_bitstream_max_size); - - /* Add the adapt sub-bitstream */ - regional_bitstreams.push_back(curr_regional_bitstream); - } + ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); /* Attention: when the fast configuration is enabled, we will start from the first bit '1' * This requires a reset signal (as we forced in the first clock cycle) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 0dd4d4ed3..52f81dcdb 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -67,6 +67,43 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const Fabric return num_bits_to_skip; } +/******************************************************************** + * Build a fabric bitstream which can be directly loaded to a configuration + * chain (either single-head or multi-bit) + * We will organize the bitstreams in each region and align them + * Logic '0' bits may be deposited to those bitstream whose length is smaller + * than the maximum bitstream among all the regions + * For example: + * Region 0: 000000001111101010 <- max. bitstream length + * Region 1: 00000011010101 <- shorter bitstream than the max.; add zeros to the head + * Region 2: 0010101111000110 <- shorter bitstream than the max.; add zeros to the head + *******************************************************************/ +ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { + /* Find the longest bitstream */ + size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + + ConfigChainFabricBitstream regional_bitstreams; + regional_bitstreams.reserve(fabric_bitstream.regions().size()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + std::vector curr_regional_bitstream; + curr_regional_bitstream.resize(regional_bitstream_max_size, false); + /* Starting index should consider the offset between the current bitstream size and + * the maximum size of regional bitstream + */ + size_t offset = regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); + for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { + curr_regional_bitstream[offset] = bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); + offset++; + } + VTR_ASSERT(offset == regional_bitstream_max_size); + + /* Add the adapt sub-bitstream */ + regional_bitstreams.push_back(curr_regional_bitstream); + } + return regional_bitstreams; +} + /******************************************************************** * Reorganize the fabric bitstream for frame-based protocol * by the same address across regions: diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index 1ad04dc39..4da8c3c92 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -24,6 +24,12 @@ size_t find_fabric_regional_bitstream_max_size(const FabricBitstream& fabric_bit size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const FabricBitstream& fabric_bitstream, const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip); + +/* Alias to a specific organization of bitstreams for frame-based configuration protocol */ +typedef std::vector> ConfigChainFabricBitstream; +ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream); + /* Alias to a specific organization of bitstreams for frame-based configuration protocol */ typedef std::map> FrameFabricBitstream; FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); From 934918d9c06450a84ae3803024efc6d3acd59717 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Apr 2021 15:06:53 -0600 Subject: [PATCH 098/352] [Tool] Reworked fabric bitstream output file in plain text format; Support multiple regions --- .../write_text_fabric_bitstream.cpp | 153 +++++++++++++++++- 1 file changed, 145 insertions(+), 8 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index f96747212..3fa604de1 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -17,6 +17,7 @@ #include "openfpga_naming.h" #include "bitstream_manager_utils.h" +#include "fabric_bitstream_utils.h" #include "write_text_fabric_bitstream.h" /* begin namespace openfpga */ @@ -80,6 +81,124 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp, return 0; } + +/******************************************************************** + * Write the flatten fabric bitstream to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const ConfigProtocol& config_protocol) { + int status = 0; + for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) { + status = write_fabric_config_bit_to_text_file(fp, bitstream_manager, + fabric_bitstream, + fabric_bit, + config_protocol.type()); + if (1 == status) { + return status; + } + } + + return status; +} + +/******************************************************************** + * Write the fabric bitstream fitting a configuration chain protocol + * to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { + int status = 0; + + size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); + + for (size_t ibit = 0; ibit < regional_bitstream_max_size; ++ibit) { + for (const auto& region_bitstream : regional_bitstreams) { + fp << region_bitstream[ibit]; + } + fp << std::endl; + } + + return status; +} + +/******************************************************************** + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, + const FabricBitstream& fabric_bitstream) { + int status = 0; + + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + + for (const auto& addr_din_pair : fabric_bits_by_addr) { + /* Write BL address code */ + fp << addr_din_pair.first.first; + fp << " "; + + /* Write WL address code */ + fp << addr_din_pair.first.second; + fp << " "; + + /* Write data input */ + for (const bool& din_value : addr_din_pair.second) { + fp << din_value; + } + fp << std::endl; + } + + return status; +} + +/******************************************************************** + * Write the fabric bitstream fitting a frame-based protocol + * to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, + const FabricBitstream& fabric_bitstream) { + int status = 0; + + FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + + for (const auto& addr_din_pair : fabric_bits_by_addr) { + /* Write address code */ + fp << addr_din_pair.first; + fp << " "; + + /* Write data input */ + for (const bool& din_value : addr_din_pair.second) { + fp << din_value; + } + fp << std::endl; + } + + return status; +} + /******************************************************************** * Write the fabric bitstream to a plain text file * Notes: @@ -113,15 +232,33 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage /* Output fabric bitstream to the file */ int status = 0; - for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) { - status = write_fabric_config_bit_to_text_file(fp, bitstream_manager, - fabric_bitstream, - fabric_bit, - config_protocol.type()); - if (1 == status) { - break; - } + switch (config_protocol.type()) { + case CONFIG_MEM_STANDALONE: + status = write_flatten_fabric_bitstream_to_text_file(fp, + bitstream_manager, + fabric_bitstream, + config_protocol); + break; + case CONFIG_MEM_SCAN_CHAIN: + status = write_config_chain_fabric_bitstream_to_text_file(fp, + bitstream_manager, + fabric_bitstream); + break; + case CONFIG_MEM_MEMORY_BANK: + status = write_memory_bank_fabric_bitstream_to_text_file(fp, + fabric_bitstream); + break; + case CONFIG_MEM_FRAME_BASED: + status = write_frame_based_fabric_bitstream_to_text_file(fp, + fabric_bitstream); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + status = 1; } + + /* Print an end to the file here */ fp << std::endl; From 03b68a1fdda83b17f85bee2d9cf6e48ba4a213b3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Apr 2021 15:25:39 -0600 Subject: [PATCH 099/352] [Tool] Reworked fabric bitstream XML writer to consider multiple configuration regions --- .../write_xml_fabric_bitstream.cpp | 69 ++++++++++++++++--- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp index 32d5a209c..a79c73223 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -71,12 +71,13 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const FabricBitId& fabric_bit, - const e_config_protocol_type& config_type) { + const e_config_protocol_type& config_type, + const int& xml_hierarchy_depth) { if (false == valid_file_stream(fp)) { return 1; } - write_tab_to_file(fp, 1); + write_tab_to_file(fp, xml_hierarchy_depth); fp << "\n"; - write_tab_to_file(fp, 2); + write_tab_to_file(fp, xml_hierarchy_depth + 1); fp << "\n"; return 0; } +/******************************************************************** + * Write the fabric bitstream in a specific configuration region to an XML file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_region, + const e_config_protocol_type& config_type, + const int& xml_hierarchy_depth) { + if (false == valid_file_stream(fp)) { + return 1; + } + + int status = 0; + + write_tab_to_file(fp, xml_hierarchy_depth); + fp << "\n"; + + for (const FabricBitId& fabric_bit : fabric_bitstream.region_bits(fabric_region)) { + status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager, + fabric_bitstream, + fabric_bit, + config_type, + xml_hierarchy_depth + 1); + if (1 == status) { + return status; + } + } + + write_tab_to_file(fp, xml_hierarchy_depth); + fp << "\n"; + + return status; +} + /******************************************************************** * Write the fabric bitstream to an XML file * Notes: @@ -173,15 +218,17 @@ int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager /* Write XML head */ write_fabric_bitstream_xml_file_head(fp); + int xml_hierarchy_depth = 0; fp << "\n"; /* Output fabric bitstream to the file */ int status = 0; - for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) { - status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager, - fabric_bitstream, - fabric_bit, - config_protocol.type()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + status = write_fabric_regional_config_bit_to_xml_file(fp, bitstream_manager, + fabric_bitstream, + region, + config_protocol.type(), + xml_hierarchy_depth + 1); if (1 == status) { break; } From 7c6e000be82824206d0e3b4b69cbc37c128ac1bc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Apr 2021 15:36:02 -0600 Subject: [PATCH 100/352] [Tool] bug fix --- openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp index a79c73223..adc12ce73 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -162,7 +162,7 @@ int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, int status = 0; write_tab_to_file(fp, xml_hierarchy_depth); - fp << " Date: Sat, 10 Apr 2021 15:45:39 -0600 Subject: [PATCH 101/352] [Doc] Update documentation on the changes on fabric bitstream file formats --- .../manual/file_formats/fabric_bitstream.rst | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index ce321cc81..11faca959 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -19,11 +19,31 @@ The information depends on the type of configuration procotol. .. option:: scan_chain - A line consisting of ``0`` | ``1`` + Multiple lines consisting of ``0`` | ``1`` + + For example, a bitstream for 1 configuration regions: + + .. code-block:: xml + + 0 + 1 + 0 + 0 + + For example, a bitstream for 4 configuration regions: + + .. code-block:: xml + + 0000 + 1010 + 0110 + 0120 + + .. note:: When there are multiple configuration regions, each line may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. .. option:: memory_bank - Multiple lines will be included, each of which is organized as

. + Multiple lines will be included, each of which is organized as
. Note that due to the use of Bit-Line and Word-Line decoders, every two lines are paired. The first line represents the Bit-Line address and configuration bit. The second line represents the Word-Line address and configuration bit. @@ -39,11 +59,15 @@ The information depends on the type of configuration procotol. + .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. + .. option:: frame_based - Multiple lines will be included, each of which is organized as
. + Multiple lines will be included, each of which is organized as
. Note that the address may include don't care bit which is denoted as ``x``. - OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches. + + .. note:: OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches. + For example .. code-block:: xml @@ -53,6 +77,7 @@ The information depends on the type of configuration procotol. ... + .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. .. _file_formats_fabric_bitstream_xml: @@ -61,7 +86,21 @@ XML (.xml) This file format is designed to generate testbenches using external tools, e.g., CocoTB. -In principle, the file consist a number of XML node ````, each bit contains the following attributes: +In principle, the file consist a number of XML node ````, each region has a unique id, and contains a number of XML nodes ````. + +- ``id``: The unique id of a configuration region in the fabric bitstream. + +A quick example: + +.. code-block:: xml + + + + + + + +Each XML node ```` contains the following attributes: - ``id``: The unique id of the configuration bit in the fabric bitstream. From a4893e27cfd6386a4021f0f0fd3828306463ea17 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 11 Apr 2021 17:26:27 -0600 Subject: [PATCH 102/352] [Test] Update generate_fabric and generate_testbench test cases; Now generate_testbench tese case use the fabric netlist generated by the generate_fabric test case to run HDL verification --- .../generate_fabric_example_script.openfpga | 2 +- .../generate_testbench_example_script.openfpga | 2 +- .../basic_tests/generate_fabric/config/task.conf | 4 ++++ .../generate_testbench/config/task.conf | 14 +++++++++----- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga index fcbf6e144..467cac0c3 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga @@ -26,7 +26,7 @@ write_fabric_hierarchy --file ./fabric_hierarchy.txt # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist -write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose +write_fabric_verilog --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga index b88e5370a..197c350bd 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga @@ -51,7 +51,7 @@ write_fabric_bitstream --file fabric_bitstream --format xml # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./TESTBENCH --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} # Write the SDC to run timing analysis for a mapped FPGA fabric write_analysis_sdc --file ./SDC_analysis diff --git a/openfpga_flow/tasks/basic_tests/generate_fabric/config/task.conf b/openfpga_flow/tasks/basic_tests/generate_fabric/config/task.conf index db41b7f5a..958c8b9ec 100644 --- a/openfpga_flow/tasks/basic_tests/generate_fabric/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/generate_fabric/config/task.conf @@ -20,6 +20,10 @@ arch_variable_file=${PATH:TASK_DIR}/design_variables.yml openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +# Use a absolute path for the Verilog netlists to be generated +# This is designed to allow the test case 'basic_tests/generate_testbench' +# to use the Verilog netlists along with testbenches in HDL simulation +openfpga_verilog_output_dir=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/generate_fabric/latest/k6_frac_N10_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/generate_testbench/config/task.conf b/openfpga_flow/tasks/basic_tests/generate_testbench/config/task.conf index 42d3c5733..db8399fbb 100644 --- a/openfpga_flow/tasks/basic_tests/generate_testbench/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/generate_testbench/config/task.conf @@ -12,23 +12,27 @@ power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml power_analysis = true spice_output=false verilog_output=true -timeout_each_job = 20*60 -fpga_flow=vpr_blif +timeout_each_job = 1*60 +fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +# Here, we use a fabric netlist generated by another task +# to show case the correctness of testbench generator +# Caution: You MUST run the task 'basic_tests/generate_fabric' +# before this task!!! +openfpga_fabric_verilog_netlist=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/generate_fabric/latest/k6_frac_N10_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/fabric_netlists.v [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v [SYNTHESIS_PARAM] bench0_top = and2 -bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act -bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 94c4c817eb5c20394618e0eeb136b404ef967721 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 11 Apr 2021 20:14:09 -0600 Subject: [PATCH 103/352] [Test] Expand sdc time unit test to sweep all the available units --- .../sdc_time_unit_example_script.openfpga | 2 +- .../sdc_time_unit_Ms/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_as/config/task.conf | 38 +++++++++++++++++++ .../config/task.conf | 1 + .../sdc_time_unit_fs/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_ks/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_ms/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_ns/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_ps/config/task.conf | 38 +++++++++++++++++++ .../sdc_time_unit_us/config/task.conf | 38 +++++++++++++++++++ 10 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_Ms/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_as/config/task.conf rename openfpga_flow/tasks/fpga_sdc/sdc_time_unit/{ => sdc_time_unit_default}/config/task.conf (98%) create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_fs/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ks/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ms/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ns/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ps/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_us/config/task.conf diff --git a/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga index 6887cd8a4..f2461f723 100644 --- a/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga @@ -56,7 +56,7 @@ write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE # Write the SDC files for PnR backend # - Turn on every options here -write_pnr_sdc --time_unit ps --file ./SDC +write_pnr_sdc --time_unit ${OPENFPGA_SDC_TIME_UNIT} --file ./SDC # Write SDC to disable timing for configure ports write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_Ms/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_Ms/config/task.conf new file mode 100644 index 000000000..d7f988af5 --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_Ms/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=Ms + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_as/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_as/config/task.conf new file mode 100644 index 000000000..ad84fe5ad --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_as/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=as + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_default/config/task.conf similarity index 98% rename from openfpga_flow/tasks/fpga_sdc/sdc_time_unit/config/task.conf rename to openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_default/config/task.conf index 88e4314d6..db23c45de 100644 --- a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/config/task.conf +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_default/config/task.conf @@ -19,6 +19,7 @@ fpga_flow=vpr_blif openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=s [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_fs/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_fs/config/task.conf new file mode 100644 index 000000000..1bcbd0e88 --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_fs/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=fs + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ks/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ks/config/task.conf new file mode 100644 index 000000000..5d8005eff --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ks/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=ks + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ms/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ms/config/task.conf new file mode 100644 index 000000000..be0a5abef --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ms/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=ms + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ns/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ns/config/task.conf new file mode 100644 index 000000000..1c9166bd6 --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ns/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=ns + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ps/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ps/config/task.conf new file mode 100644 index 000000000..cd347fb06 --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_ps/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=ps + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_us/config/task.conf b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_us/config/task.conf new file mode 100644 index 000000000..a7becff2b --- /dev/null +++ b/openfpga_flow/tasks/fpga_sdc/sdc_time_unit/sdc_time_unit_us/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sdc_time_unit=us + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From 07f6066c11b1c86c089d7f934040194d399f321c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 11 Apr 2021 20:24:18 -0600 Subject: [PATCH 104/352] [Script] Update timing unit in SDC example script --- .../sdc_time_unit_example_script.openfpga | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga index f2461f723..3810aa37b 100644 --- a/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/sdc_time_unit_example_script.openfpga @@ -42,18 +42,6 @@ build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream. # Build fabric-dependent bitstream build_fabric_bitstream --verbose -# Write the Verilog netlist for FPGA fabric -# - Enable the use of explicit port mapping in Verilog netlist -write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose - -# Write the Verilog testbench for FPGA fabric -# - We suggest the use of same output directory as fabric Verilog netlists -# - Must specify the reference benchmark file if you want to output any testbenches -# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA -# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase -# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping - # Write the SDC files for PnR backend # - Turn on every options here write_pnr_sdc --time_unit ${OPENFPGA_SDC_TIME_UNIT} --file ./SDC @@ -62,7 +50,7 @@ write_pnr_sdc --time_unit ${OPENFPGA_SDC_TIME_UNIT} --file ./SDC write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc # Write the SDC to run timing analysis for a mapped FPGA fabric -write_analysis_sdc --time_unit ps --file ./SDC_analysis +write_analysis_sdc --time_unit ${OPENFPGA_SDC_TIME_UNIT} --file ./SDC_analysis # Finish and exit OpenFPGA exit From 1db8bd7eecd7aaf7eb842aa7f9ac1d33fe850742 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 11 Apr 2021 20:24:32 -0600 Subject: [PATCH 105/352] [Test] Update regression test with new SDC tests --- .../regression_test_scripts/fpga_sdc_reg_test.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/regression_test_scripts/fpga_sdc_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_sdc_reg_test.sh index c4ff67a09..713c328b9 100755 --- a/openfpga_flow/regression_test_scripts/fpga_sdc_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_sdc_reg_test.sh @@ -9,4 +9,12 @@ PYTHON_EXEC=python3.8 echo -e "FPGA-SDC regression tests"; echo -e "Testing SDC generation with time units"; -run-task fpga_sdc/sdc_time_unit --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_as --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_fs --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_ps --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_ns --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_us --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_ms --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_default --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_ks --debug --show_thread_logs +run-task fpga_sdc/sdc_time_unit/sdc_time_unit_Ms --debug --show_thread_logs From f626b17d04bb9661da12ce2a3f8ccbcdef256461 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 13:58:19 -0600 Subject: [PATCH 106/352] Update user_defined_temp_tutorial Change "example" in the beginning of the page to "tutorial" for clarity --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 943993aaa..3f12839d4 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,9 +5,9 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this example, we will show how and when to use the ``user_defined_template.v`` file. +Through this tutorial, we will show how and when to use the ``user_defined_template.v`` file. -For this example, we are using a modified version of the hard adder task that comes with OpenFPGA. +To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: .. code-block:: bash From a2c2b634e60673ae8c4f35763aea877c9da3895f Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:00:54 -0600 Subject: [PATCH 107/352] Update link for _user_defined_template.v This ensures it goes to the correct page after pull request 274 no longer works --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 3f12839d4..cbc161971 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -167,4 +167,4 @@ Finally, rerun this command from the OpenFPGA root directory to ensure it is wor python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -.. _user_defined_template.v: https://openfpga--274.org.readthedocs.build/en/274/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v +.. _user_defined_template.v: https://openfpga.readthedocs.io/en/master/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v From b176ca6c0c67f3d791b7df2145aee75e31d3412a Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:13:41 -0600 Subject: [PATCH 108/352] Update to improve readability --- .../arch_modeling/open_cell_libraries_tutorial.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index e7d232ca3..d3e7e37d5 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -246,8 +246,11 @@ We continue the circuit model creation process by replacing **LINE67** to **LINE .. note:: The name of the circuit model must be consistent with the standard cell! -The most significant differences from the control in this section are changing the ``name`` and ``prefix`` to match the module name from Skywater's cell library and including a path -to the verilog file using ``verilog_netlist``. The second change to ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` is at **LINE160**, where we will be replacing the line with the following: +The most significant differences from the OpenFPGA Circuit Model in this section are: + - Change the ``name`` and ``prefix`` to match the module name from Skywater's cell library + - Include a path to the verilog file using ``verilog_netlist``. + +The second change to ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` is at **LINE160**, where we will be replacing the line with the following: .. code-block:: xml @@ -288,7 +291,7 @@ Replace all the text within ``iverilog_output.txt`` with the following: iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 -We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our From Verilog to `Verification`_ tutorial. From the root +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our :ref:`verilog2verification` tutorial. From the root directory, run the following commands: .. code-block:: bash From 198882da8962076ee5bcafec378da5da5917457d Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:20:40 -0600 Subject: [PATCH 109/352] Update link to From Verilog to Verification --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index d3e7e37d5..86e8ccaf2 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -291,7 +291,7 @@ Replace all the text within ``iverilog_output.txt`` with the following: iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 -We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our :ref:`verilog2verification` tutorial. From the root +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our `From Verilog to Verification `_ tutorial. From the root directory, run the following commands: .. code-block:: bash From 90df365259fecb7c7f421022bcd69cacc0ea499e Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:21:53 -0600 Subject: [PATCH 110/352] Fix a spacing issue on line 250 --- docs/source/tutorials/arch_modeling/Spypads_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst index 4b426e20c..26fbb58e2 100644 --- a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst @@ -247,7 +247,7 @@ The waveforms will appear similar to :numref:`fig_spypad_waves` Building Spypads ~~~~~~~~~~~~~~~~ -We will modify the``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file found in OpenFPGA to expose the **sumout** output from the **ADDF** module. We can start modifying +We will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file found in OpenFPGA to expose the **sumout** output from the **ADDF** module. We can start modifying the file by running the following command: .. code-block:: bash From 1744ce594eef5890131a35f2bcabaa20fcbf57e1 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 16:06:44 -0600 Subject: [PATCH 111/352] Rename Spypads_tutorial.rst to spypads_tutorial.rst --- .../arch_modeling/{Spypads_tutorial.rst => spypads_tutorial.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/source/tutorials/arch_modeling/{Spypads_tutorial.rst => spypads_tutorial.rst} (100%) diff --git a/docs/source/tutorials/arch_modeling/Spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst similarity index 100% rename from docs/source/tutorials/arch_modeling/Spypads_tutorial.rst rename to docs/source/tutorials/arch_modeling/spypads_tutorial.rst From bad49cdb75c6ff27ed6acaeb486b295c41ac6955 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 16:07:38 -0600 Subject: [PATCH 112/352] Update to change Spypads to spypads --- docs/source/tutorials/arch_modeling/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/index.rst b/docs/source/tutorials/arch_modeling/index.rst index b6c27e69e..3649516bb 100644 --- a/docs/source/tutorials/arch_modeling/index.rst +++ b/docs/source/tutorials/arch_modeling/index.rst @@ -10,4 +10,4 @@ Architecture Modeling quick_start user_defined_temp_tutorial open_cell_libraries_tutorial - Spypads_tutorial + spypads_tutorial From 64e8e623a54b6e3a8a69ebe7dd40bd10c3c40b04 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 16:14:00 -0600 Subject: [PATCH 113/352] Update to fix links to proper syntax --- .../arch_modeling/open_cell_libraries_tutorial.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 86e8ccaf2..2255c22f0 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -291,7 +291,7 @@ Replace all the text within ``iverilog_output.txt`` with the following: iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 -We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our `From Verilog to Verification `_ tutorial. From the root +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our :ref:`from_verilog_to_verification` tutorial. From the root directory, run the following commands: .. code-block:: bash @@ -474,12 +474,12 @@ The simulation waveforms should look similar to the following :numref:`fig_custo Simulation Waveforms with Skywater PDK Circuit Model -We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please `contact`_ us. +We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please :ref:`contact` us. + -.. _Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ .. _PDK: https://github.com/google/skywater-pdk .. _GTKWave: https://github.com/gtkwave/gtkwave -.. _contact: https://openfpga.readthedocs.io/en/master/contact/ + From a0b01dccc7891a72bab3288f3e9e9b87965107ed Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 17:02:56 -0600 Subject: [PATCH 114/352] Update spypads_tutorial.rst to address comments Add links to github OpenFPGA architecture files, reference fig_gpout_ports, instead of emphasize lines switch to numbering the important lines --- .../arch_modeling/spypads_tutorial.rst | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 26fbb58e2..48ab5f4b6 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -21,21 +21,14 @@ To create a spypad, the ``port type`` needs to be set to **output** and ``is_glo -When the port is syntactically correct, the outputs are independently wired from different instances to separated FPGA outputs and would physically look like :numref:`fig_gpout`: +When the port is syntactically correct, the outputs are independently wired from different instances to separated FPGA outputs and would physically look like :ref:`fig_gpout_ports` -.. _fig_gpout: -.. figure:: ./figures/gpout_ports.png - :scale: 100% - - Diagram for General Purpose Output - -.. note:: The general-purpose outputs are not applicable to routing multiplexer outputs Pre-Built Spypads ~~~~~~~~~~~~~~~~~ -An OpenFPGA architecture file that contains spypads and has a task that references it is the ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml`` +An OpenFPGA architecture file that contains spypads and has a task that references it is the `k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml `_ file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml`` by entering the following command at the root directory of OpenFPGA: .. code-block:: bash @@ -45,7 +38,6 @@ file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_op The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172** .. code-block:: xml - :emphasize-lines: 10, 11, 12 @@ -56,9 +48,9 @@ The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac - - - + LINE181 + LINE182 + LINE183 @@ -217,7 +209,7 @@ If we look at the module definition and ports of ``fpga_top.v`` we should see th //----- OUTPUT PORTS ----- output [0:0] ccff_tail; -Using :numref:`fig_gpout` as a guide, we can relate our task like :numref:`fig_gpout_example` +Using :ref:`fig_gpout_ports` as a guide, we can relate our task like :numref:`fig_gpout_example` .. _fig_gpout: @@ -247,7 +239,7 @@ The waveforms will appear similar to :numref:`fig_spypad_waves` Building Spypads ~~~~~~~~~~~~~~~~ -We will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file found in OpenFPGA to expose the **sumout** output from the **ADDF** module. We can start modifying +We will modify the `k6_frac_N10_adder_chain_40nm_openfpga.xml `_ file found in OpenFPGA to expose the **sumout** output from the **ADDF** module. We can start modifying the file by running the following command: .. code-block:: bash @@ -329,6 +321,4 @@ The waveform should have some changes to its value. An example of what it may lo Conclusion ~~~~~~~~~~ -In this tutorial, we have shown how to build spypads into OpenFPGA Architectures using XML Syntax. If you have any issues, feel free to `contact`_ us. - -.. _contact: https://openfpga.readthedocs.io/en/master/contact/ +In this tutorial, we have shown how to build spypads into OpenFPGA Architectures using XML Syntax. If you have any issues, feel free to :ref:`contact` us. From bb5cd1de47b6d101e46877900f53145317a455e6 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 17:09:16 -0600 Subject: [PATCH 115/352] Update to fix :numref: error example figure --- docs/source/tutorials/arch_modeling/spypads_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 48ab5f4b6..1cbbeafe4 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -211,7 +211,7 @@ If we look at the module definition and ports of ``fpga_top.v`` we should see th Using :ref:`fig_gpout_ports` as a guide, we can relate our task like :numref:`fig_gpout_example` -.. _fig_gpout: +.. _fig_gpout_example: .. figure:: ./figures/gpout_ports_example.png :scale: 100% @@ -225,7 +225,7 @@ We can view testbench waveforms with GTKWave by running the following command fr gtkwave openfpga_flow/tasks/fpga_verilog/spypad/latest/k6_frac_N10_tileable_adder_register_scan_chain_depop50_spypad_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & -.. note::Information on GTKWave can be found on our documentation page located here: :ref:`verilog2verification` +.. note:: Information on GTKWave can be found on our documentation page located here: :ref:`from_verilog_to_verification` The waveforms will appear similar to :numref:`fig_spypad_waves` From 0606479bf8310c1ee360057d0279dec00c18c029 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 12 Apr 2021 17:53:31 -0600 Subject: [PATCH 116/352] Edit figures to better fit page --- .../figures/gpout_ports_example.png | Bin 19860 -> 19825 bytes .../figures/spyadder_waveform.png | Bin 13439 -> 11849 bytes .../figures/spypad_waveforms.png | Bin 24078 -> 21301 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/figures/gpout_ports_example.png b/docs/source/tutorials/arch_modeling/figures/gpout_ports_example.png index a862d336545a6d2822cdffbd22a6287673929196..c74dad3b4a61c2575b4228d7f5671f1d3b6fddc1 100644 GIT binary patch literal 19825 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 literal 19860 zcmdSA1yq!6+cr8V0)n)H(x7w+NDL_@(j_1;fJ!&a&?z8N0@B^x(hRLg4&B`~q(e9R z_IaN7dEfW@-f#c^{`XpYtvzeq%sCfV+*h6Fb)3g}1*s^>;9`?ugFql$+1FBPAP|~0 z@c3h404aPVnSH<)8ca<_0#w>hfdqb_n~E!ngFxlsI9KoQ0l)9tz1D_-Ksdy|A2d*6 z@?#+JtMOY|6GcT33m{{GFwihScL50vbO-oD^p}hV$Yh}3RR9u56OH_DSs#t*pZNpK zLFj+wF#*1Re_jL6?=pXW-%UsRXN~E1{*fCEH~sG4vf%Gx^l9C?AkZBg^EYoD-YO~x z8roWOyf?D_V9eoSZTC9^NZ3UX5Uq_J-qW~PTiL(_T}0^q$RP;GzmqxXX#U9JU@1cP zR#AmU(iUn=!^`o4<2juuHVqApFx1FIP)+L9U&Vo6B6MaB4t9c^oX*b99L_u(wop?} zE-)C(`J9`Ro0}cT!47k^ad_{-ZUcMzXC?orN6Hvx2sO8JFt@d#`Cae(54MgDB6M`W z8~Xe6=X*MsoBXpS8`xjn0y@a~`#+pq9M3ubt{W&S{5w@p8ES3}wEVk%Q7+*>a{gP| zKil~;zlxcygDo%$P;*0B8wX>k9TXUmKT31|Rr-I<@n7pwGltn(IsPuJVPozf`i~0! zOY(m$C24C7Gzx?Leq-Lh+WgnFzw!%n{vNJ>8NNT~=8sfhazwF(Iscw$QS5=R;9w9) z&Pi5E{EdtL?i{AaL+MM*UyKfDNCLNr!K8b*4C$GfUteoI6h}R}heP(prTt(UC$JI2 z^;nqz9o+*>mEbj#?>pI#aU{=2pS@N^kC@M%_fCZ;816&kw&P|H`v}uI>)P4|XICfS z!_Y%V00PBJ5FP`2j^SfEF6bQ{)-)gz{o>v|+!z=+*_~l#WtGR9DAEdFUS7^O>W(~W z!xtN5ubq`3<$$DLU!E2@6KE8u`S--K7j-~Zj-M=ORal z9pTiraF6o}9d3u8-R%`#*KWKd!WkFIcGYG>bi77mSu*(NGeJQ?%wP8@>11B|o-})2 zvMDC<#fbGxS6k{rVX!d@Ry?~kL|oh<*sSs%4#}i%dY*U^yI%e1iKw?P-=PEf$=;l$ zZrDh(57@j9WjVS@eEz-OLDBt;ms!sW37!$}b>swK^)_9L@=mhB)SfzdIv` z=@EL)bH=W>*QaCAi&$eDpIGgs&6)M;tH>(rFZUYOob~gRC|x~39&64Ce58(n6xnP< zLBYY91?qXjyc3YDb)BF^sSr}mTsrAe4+tE(Hu}{$n3S{h^VRQxV@2mRS`+Zv9HhNC z-$;{P&0Rf{q4ty-$yJPM8xXx@oAWsAgT|xEpYU2lQ;@*9+;*!cR_(q8y%d*~m3^k< zW+7+yX$$s4!^DI^biJUj@#oFg)rMj z)aR13kFci~o*fVlQlDAp1LUJE1FgKkD+C4JrU5B|HJk^y+t4m*>oBw)Mp zATAk%*9DSMyJ{$1{H}Zqi-r+ldq*hw7-V8*adUGht7c6AydKSmq8@Ll z7_SqKw5tPoe?{#BCtm>V1EehTgMCQ1k?!^M#xVH+c3+#SG*k#0}(H{J0 z&Gc6tp@Cwx^^7Koi2YuQnC|7pcG+&tQp0|8WtHWGl8twZ*Y&FNQXh00*dXTcn~QDZ zq45;wdGqe>ZdF(@#F~dRK+kbZqvm>JVEF^#&D{3D`Ui=umpjxCIlM5f^&Yea-42SZ zvAu(q-!%|DsDi^brel|)zIR74u5ovy_kB;iI}pl0&(sMojt}9UEYv76dbvvTQ_My$ z_ie3>9s)U%x5n**J$*V03x|lUKp`s?kecl;UDi{v+BH@Qi53Ga4GS4cI>KxDPOu8+0A-o5c$P%`fp(}C0&#>Z3}r{->CjH2aFYR!)}hb))} z;^bvzBStPx_ie#;iyw2WrYa5uHbDsse0jOKJ^P>YP~46C9(NWOa7f7y9QuXLd}hU% zgs!8Gt^-p&PqcZ*L`>15{LsQ-HqvpPT1A?QO76&WhB=Ll0Q9@Yq$6k97=qP*PkY4OTIsn7Y_OCT0v13 z<;S9&BDI4_;K8x}+2xX3^*3 zpWzCz_CgFO%+lCzoyLs{=nO<+5HK5b8Z^THHCM>$-*?_;>3opKPeB3k!U z3VhSGEJ*dBx(BrcG1%&y1?qJWV?A9Z+k9~e4*MBHKq>5^g4g-;r%L&U_SX=_!2oKn z*G=xHxnI6KAcA{<4OZ3Gisqd~y~z2jzP5GjE+7B0m7r#g5Q;79jasV{PV{EA8b}p6 zX#Rv%3QZ38Yq0JQM+sEE+^2p><$6oh^pKpq=yTvt`b@Hl<%_Nc=lxt6D%YQ}fWpC@p|1v!PR z)~(jzc}!D#UuAqQoosOC)NA(84khHZnSF~pb$IM@7GhhqwUUsM!ftT4?@V`T0c&OD z><12Km)oA(Lc+YaAqZi6d(6d6WoSwfx3Z91<9cXvaecZ_;C*}Ztn~3_n9!bGL*G1B z`;EBKfsh%w<*UcufnQ(*5ceOOX}4E-hyWaiMPe<`L5w{|>=W2gn2W1t?aj1hSxnjT zfm*7{yvL!UoRU(mxF1G0(&r~Q6R>5vC4?P}fq*qF;Mx!$IO|*hG~f)M(82Gw_45%; z<+T|7TIOR??2}a%_T{LVr|A}=E{oG~Gf|)}gBx)b8upm$M=TLB@tjR1KlX=P8tya7 zD)*Be+1h!xB8v6dPCz9w2k?3k4Zk*+2E(q8ClFemQ(Z^TNgV}-ef*1N%`b*;qLf7= z;PhTS_KU4PPH-Yaf}>9>2W}pK@`GM}5l@22?>8QXkv+Y*Ivf}qd<0wXRh5*wy_jf$ zXc``^x;zdq<2V7kpA>uWa<4BR*~9$P_C_6s)YHZCj1jRGfo4}{sDmv(lx$E-?RIH{ zQW#IuK*!4B&gmkj7gTG*?HpUqd*JePKM$}-y}Nus5BI|C#doNsFk1Zh3|xz0xIzM_wE@p)Kq{~Ydv^tAFigWJz?q+mk1o&flkQs1)jO`$jTdQgx?S$pu2KK; zy@z9DH{lY07qm}oaL+Cxf)&^${e;jdmX&21QS*Zs{|*EX2mi(?7e|BVc1f+-RE04V zk|gZPO)2E0FwSg3k$;{F!dcyTe$zAy8xVoUBTm7LLeSOMf0*G|w{tF7M`scbs4@Kh{rjVZ8mzT5y$&N76kX>H)X(32 zq?kzaUjBJMAq(&5Mx2%oN{mM9^*R>l>V%WC-W8K^HB+e`-JOQw7Q`4rDr|xdx(XHL z>dT# zL&!p$C7qojfj;$q9^)(}KA*)Xlj|4PnY#Maa-GK$+iN;_Us|Z=NlMjkfVG4$2M#VZ z>%V6sG)UppskTQa2R1(*Yx z4ZQ)fu!_mFq-|G<9gnKl*q46)UM(!F7iRAXTRH91IL;+2T!hb<+~5X(WZghHcU0Td zIR%Q^B-aVj;*8#iFA@F1$eIKWdS;zrl-zk8{7=C_?{e1bJEfmo+?OY$*x`V~ixY{< zqF_TFei8eHLgUl#Je*S|zR!GjX}X$!8BKbywtu?d&B+OCr!Gz0qSz>|v6*8r0C(or zcB-FK;)h!D+VzLP>;&_+A8ZVtu}-vuW&;K0TqgKMn(ozJO~S%9vWDd6jgRX+dNV&)0gT;FDt86E zyDwc18WhNT6(@vDl7-Me{`#EkMB5R!3c=ULv}}H{LEe2~!U6h3jSj$aVsR7}=wlF# z*tcspVFv~syy%7zStjf^h6>REIQBsNL8vb03ZFlG7vBc|Y2>W?ev_!!yC2q>c1cSh z(D$#lgX*@pte7mIS|i@ORyWJ={1mgG>0+yBwA@f8p^hF79C1{Evu}ZF)~gCVwRwo-{&-!<@*VUwdF+ZN|OR-9s3X~&x@l75#+D?n+18P zktKCctfwlZZAjz#YOQDZl%16!nti)0+q;XNE1EY)0*r>*H9Qc9A7B>_z9lM~Gb2pU z;-h9lB=cTL(!vkqTAYEVdP&EZCr|TWNxgJ|)ActK)`SL)E<@u{0(o_H0ti4Qn-hW^ zz^Tc}Y;iCK9-fgCQKi`x#{fLa)#oi~Gwmddq#;;cP_kNakF8PWbA6l2I;9jrs9>#P ziTgX-x%%poPD`5>0S1OwN*gD^d5TFUGaO2@B>cMH-uYN3?nTT_<{l}HJ%v~5&jT9P zkkCg*3DMtQ^MG0ug11ezh6WNQ{L11zyGU@V@^%g$`-_ z+3gUlw-2eQIrD;|K9<}{%3OGUvHjSe#IMXT@KbaUIEpE$=PG0Xh~tgY%D{?}_LGgD za8FyCfh1VZEFtTuO+P>Bg8RM*ymzwP&^STFeI=CNXiCHYEWm9O&;j>U{$*;{Sw4Hh z&)7`#zRUXVNB%oRRXp6>R@XE3gy3v3u4KG>c| z)ImbYct=$hH?4UvUgzdSLp7V)~%>3ifIlQFDA~DtUNt+i-%QsNG!fS z#{y6aak_0jG&B?&9sN*#tWd*xM5o5eobWrOIj!hIBVXnFaFw|_xamWCaIEX$dbjIz zl5Mj&vrbjMhwX1S!}7Cd0n+I;&z?PdE7cl@0Oqf!1`@@fxKntAx>;LY?P3XZ(*aW1 zShY%{_tz{!Js>WE)Qt0-gqv%^AdoV8V*?kU`TC=&KMYmBr~)e2UROCEa_L7Mte_w( zl5wXP#0&AW&7KXt?_t)&ro7^HB%S>!LbB*iaO%clj(xsmI?8^H!$%mLE4Un*OXO(~ z91PJtaQ=wYj;u1rg{W!z_ccg+(EmpBGCUi6O-#Z?W0s`+7SsCL@6PkPJo*K6 zW=Y}9KrsaNIW|F<;45u%3dzCGDp<%iUSK!;Wsn9jK+g&Pv`zma#)vV!upz#^W1Vvr zz~W6H*JTb^tk+T-K$~IdyyljpkEJ3fKfNVO5L63w#Q^U%ejVXU3+y+4`c8(!qgLgu zw1blF#z!{WMp^?}ZmEL(k(q^i&}moNJZn*=5ez$eQ?_;)++1mkhcpy4W|B))X3tTN zOhy+QX~Cve!qV;GImz)Iqr-y!9UU?eQPOAUk@u}FTrzU%d2F2MIspx6KFM-1PbPpH>Ozv-ajH(L#N<9@y8QBgv!7?;#fVHk8 zijqRcK9nf_YzNf!4~O5si~hkL(-CQ(zF0^}^8EaC|Gou9c#$6%=v~H#l00ksNELbX zUNmuXP^%OHuuK%t{}S7JBaY!G(L73vllIhy; zc?di*c6D71MJJtabAI5kx}$BOSjNw#4u< zLvnN{N_q9mnRyA&GwMagu@N<$w+#OFZl%mK2}}_vU0(p8oytVpvo^@ z4LQsmS29+2Vd1tru8WN9>hq}aYD(OKlt9;34{n~9`oUBrhlkC=B~@P+ZJM#rLRUcV zIIyN^p*#C6YnG1)2c0Rw5(Aw23NbRFnbK2JZ*H@~Hw*l6j5!)NdK01r3_n9oF7+Dn zJH2n^=cF$z5F~JlJlh(ZnC;D9=NoVAS6{m+70bgQGI7WebEpXeJMnhC>#~$i6^v2w zZLJbXhQfTEDhJQIJqWn$I$QRI^9&!@`sQTUA>^&tfT2gupmRTkg`f?^7#Yv!c^$Z# z66cp!&%(Y+(+QeGM!y=6Ma1XFvOT^!51Yx>rhX1hCBkuO_)g{Pghe6X8p&WYNfUrs zYc1apPMM{MiQiMPXKy*KGLy)Q+-VOv=vWMQKN<9wk6W#1NfDs!1QT%fcV`Sa&q+)F zq#lYYD0uM}{oK^1K1gu9Ou4&AYova`J8s_|BBRsd<)C-GPB0!0;&r9OZIT`x3j&^^#shtU&hq>Vt@70_q*jFL?$AqdrjUlZv~qPt-)69W-11Ny$Mxx@P7nz(>Qhz7mdH zJwJ@5^EC{y7~4FtEX`1&D_`wTG4H=V9a*Ik*<7+L%VCINMIaTzvYej0 zb*j>vOLT_P@{~v3lzXJbvLlaYY@!hBfyw;9U1O>z)?uUk%f!cY zw|_ng$zxWj368q@dgh{YHf8G2(>X2HUo)WL`^zt#Qp!X9pdo-dmzc9jYHC1K-cJfo zgEhCOk^D_DlR@>ebVwmBD+f6zyKkYUe2hjMv#Lb%t2pMT2FeC?GzJMPf)q~>Gu3F; z(<-tkQBUdT^gK~iElU{SM(Nd_bCET<*yx!bjFDi^3zdnE(6y^~FcJkwPM~S|VCKn657uRl#o{a~0MExbsFetHUrbX8Gy_dz&$u;>wPN6Q$un@D5w zdR-VdFiR&bH<^@l?1;W7?hXc_p9G+r&4VoMX$FhmQ*)jEk0;tE2i{oex(HVQn;-oH5 zYp_G$-t88vg-XVqrgUi6g~%&En>wF8+aX_;K$;TNuj0$StYEsu#^W~p(c2{3e9yW1 z(O2mHc8)H$?*$J!2@}Go1S}LWOOTUkokoIQn{^6|H-hgK14@vq5mDSJf^KrTBb`dR zBleaDo&KT;$ns6PrcoAci0#?TJX??cOPs2dhAYXzq6y=@N%ce zoKQhPgH=~k5$-#~wnX9X$Q6!g^;6W^KU~K!)ODO-i~OF^{Z`rh-%8rPojv7)*48r`4msv9y?88a7085L`Yq5`d(RF5ee^qXHk0H9rx zZ8d?gwrjVVwEv`cM{I6>MYr+`Wzi@zQXCq8Q?4VO!1AVqM*W;+t)!rWH>T)~ zQf?8eKD+u9wsA>8Bky^ZRCnYX2!)|idoXESfm!*7@n>P2jLr5XMHX&_a=X)``)hH? z5K5sI{om6H*@68$5Ta)CL8wEQV2BKKKc5kb_QCO+O4USnp69#4LE@4S#YXP=(|d6IQ6l~81i*WoHfsZM zud=4;YqCyBo69{T6Hh=-jlxx*x*4BCFVt4oogX~;FcBefJd|a8Y77t>rJEn3-jVpY+!ZI6xZnQt zeOQv>@#k8EJDoY|L!nOni#bZ-r=8~ovNpt!S}ZJ3hF|(Frh!}R`w@QY%umP><9)8$ z5J;8b6l$lKt)7tei9lGzn>>8E=-BGPZ?_IkA!KJjGl-6XLa99Ag%HuSEOp=7PepS3`( zMj2b|_Z;H(hir*`M)PyAj%KAF517`M?7UpmH$6!cHlJ8|z_=3hR4hh%aQ&q2{8N^_ zo}CS5^2|KO$3clfyo}E=EUK!6KPU1JtV3ZX<<%BbcM3Qv`Ra=cjbaGC>p6S8%ia)L zKB{3aBIb} z$zJQ!#)>g-j42 ze$~U*v0C=4AC1@dK<*7p8ivj@a8R43l#INvqe{*O7+$*sgrpE_$UQl7F=IUiM+iF%J5;N!@-Ipyrqvs z9 zL=xu5MF1U5E-^B}yZlij@sJgIv8#CZ8aKN@dy!)~s&TZ_N5L|8Fx#K5`z7;DE@eLE za9djCc*nzGWB!QJTK+rUB*>rgzdAervkUZpnffp|SDThQ!(8(gcn*U$lbx(2iphLm zk8qTyklkT|&g82RTb{G?_I0AUcYZwve!IFG`VF zZ}g7JCNKyO10T!D)lS}9;Ao3tR%$fa?JZXV+1(K*r}<)!dM%;JZLB+N_Vp~zq&ru% zl03sDn?Q091B-M@mszs0%8J5}lC;j{XJo1r7g&fHAxN)`M~O{}ZvFAww?GU=1)5;_ z+@=0IPz9nKT{Wz7GQh(AXwCfYk;N4jnHLPHPQ+MLkm7&LOJ|Q>BCDI#K@(}GeEC#e zrm)<1&DKvf1Vcvk2Rh-m$`NMfmxScFucS-=1pcM3&uvQ3lFU?e7Vq#$)c}dx6kpdu z`Bzz`J~JJAewL4FYF@8`o4n4-ctZCM^QMCiIvs&yJPo?{fiRQ=EeUm(wc~e>$hbW5tG&lv6JgWjQh2ywW-L5cC`eeHWx#ZA&bt|znfWvo(Lj|i2l0I6a^%%fbXs`Up+#l66E;mT9NKJ0Qy0fT*hh6wOcdg> ztq#vi*!8sz*{(ekHn0U1>4P7s8-m`E{C|eH!*o0^m=*t@U~Z)OM0td@)G`*Yk#%R= z$O}3y)h5=Xv&v&9vlGuZg33Yn>iX>N{SSzHIHJfZ8$aS`oD&nv- zOb_3&WmM|2$NL!qgPI-bIja()I@{KU{G`8nujeM^8(v>TH@fkbTwXh$Q*}CKA8*S{ zXp|{Azc71=3>RgAO(t*mUmPmeyPQ`*Os+&u2YuA@jJBqV6OzZPWr@Kz;(1EY#v}oI zhkV_*8nMF%BFraCj)YbGH>iMQQfv>R&oYTcJPVo7ep`h!Ha8BUjWTp;p{dJ;ce$;C=ILtH=c6oTyVe60j9Sqs9CYNh7|hl3{q3;QLlI>whEWq%>xC{030vZ5*T$~7w*nK$8pEgVXERNO5naxpeM6N z@nglAD%n(lNvnuU{FoQ^(#tpoeucH;K}Dp>>UDNC)}=(B@BtLLoD{hra`imL1xerI zb)rr744SXQrLjJj{z3Y@5I7aR!PT~(axo`-Q>{~2T(1yBbiiA$@Z{X>;>W%79*T*j zuDA20xMm}t<$_O4c+^}uQ3HiKFO-Bx_3p>0Ctz=0)DF0p&3*FhN#rT(8+j)fmDJ4;@)mhto zZT0?@gEO2sPIZMGxzPq!m~L>1o^F4D?{^}o3omEc^8&2rSz&gTm3rJ7UqBZw zwTLk@mEH@om9sE)nYBX}**?E1i5=QrT6@vy7|pDoToWR;^?v}e>0ZWvKdo%ei!mt4 zre42#Ddu(f^jdh|R4y$|=?MC5G}y@MG&hdCc})90X?()!OC>__2f9;9uWT0*Kbbtnyi$G zy(>m{XC{eKXnL$^eam5hU0b5zC$;59{9|qREPa3M7lI-w`qww^u37unLVI7)&L460 zuPs0Z8jPzgj(lAf@K6C>wukF4*f_%GFOiH1ch_ATshZ!LK{^MMY;*D3-2%K%DXW9R za?37{GQ2r-UoBY8ykalZ%!w}5V{W$5t2UORF43X4^!FGlic9>^9^MX%X_2H${}wl0 zn|Hd`sE!xlTgtnvsO_lRCi3YW&cyC;Pe>Fh<@!<`fW;AT`*j4LJM7@&;>$sfXJIKK z@{go!rcy?hw?3*@R~U~)v)1(y^_Odr9@ae&j=s7-O}W4SInPSBG0c^^%F_+2-iWj%gi{PDqhiS0I7iR%Xp*S_TyPGxX0?xHNENZ}n)+l8Ae%(C8E-Bci+n z!3pa-3(EVwDe}7w&b9Zfo{Is-AFH*Ux+wrJXMmf>e7Pgk!B&k(BVR|O&;K=GQs1d1 zyNB%$`OT;DE3X#@cpMS7SD9z6OJqwV@Wo5i#hG7brr*pT0kBymSML{qYGHZ(DOm&j zR_O-eR2u3B&U?$!iRTE;s`FMf-gY5vzzu2i#Md@})+(wl_FFpg_ z&(vI%K*e7riU&^jCO_y~N%)c-;OU&>;A2g{w`!_eZ8APEA`|d#E)mba+9B~tAUC|z6<3}g z5+X92^BZ=@Vgx<_D*6XJ-ty5bF-n>RseB`-x?YqY;I_KRRg8Y_S-&H)e!{GN5KTGI z-;+tMrelf9#syefeEt@WhW(1d+WvE6d5D%MilFo#x`(6UQP=$)KE@+!nBQxZpWKTeAcUVMI8la7$&C)Jjjq#5oUhoAi3aUdpIvB zp4hjB+5@R=GC7UIV1tB1v-P zh*vs&gX4#b=!ms3=ABc)%G*`h1}am5C(0C{cT~VpXY`vIJqwHP8JR|NiG3dWKf$Y2 z`FH_4t#5;2wNUPc5a84EWy71Y5m2>b#OM&5{G;%11fEbNADit3#4yp+Yu>Zj3yDbM zUhO9;454s_qzG2M>%>c}wNA2XahodDgTh5R!@8YH;XL>B`6norPMd0eTm+uja4r1L z5Vf|y$P>1M!T?ENiqGKBKJ8ui!(1B)$nv^LP;=hPR-P!0IsBZRGej0)=*7aT5vKgM zC3X08FGrb(Xf?EpgDz0?*O(SSjbJG5PDPb!rEDtg&8LuQl`4ps_GR`^d%VM$uB@?& z7`t%ew`2%WKa-VJ`WwDpfgYS%wRMEF_UeTkTg)fx?+yB#1c7eD0gKA7RhrFj)6low z{~2(-OBrgGM7D9V>9L&N14-cHzIsH^%zPgAx+5u!>{RWC9^gim*jqp?B1dZa9iMEh zI|rZ7rak=wvnrh*Sd_wMN$EGn&p)ZKq+#0C^*ig@-+8hjdHHZmCOmfug*uXeBqtJ4 z)T5XTyh(j>y-k-+PFL<<^LK<70MuEY-b3@07wNcmxU*S zxchQ3!v%fk7jZOX^~agHLMbXTt);zUYU?{~$MGoZJvg4g{~w^Nf@&`AI}D}~fXm(f zjevd0?qJ#O5)qFPytMOoR3ZoY;()CW#S{KZfYE0gcNSN(nST;hf#y{To*UI9udj@Szs;PkiW~%=bwRV2KI8Jtb|{ zWhw@;mB3!c^3Q)QBY2WIdKxr8c^!~kbDsXc2hRVEDE%9<|4*s^_e?55)m^KxX3tUA z=@(Nf-a)nVnepX@1;bqt55>%ha`xwnVxiW6rhD;Wiko+x+asAwpyCZCF*a4d4j0YLBjJdK|4QXCRa^e@1Uj|vyqigNd(G)ciY#K+U4gkskcWwMS{yY`s^w7a+UMC6B4QvinrH;h|P!kQ(nBE6SO!+=Dl!Tc?IwN2#2jT zo9#MXRb4BDAx}Y*)>)9!lsYRLbsA3rO8Eg{_&Ol09CymG7@r9OU$?`fVtcb2EVu{ zZODK9CYmjrip}?mhks6ra(g0gb*#vIZodU_Dp2~g#6YaR)XlLzOZ={!_mOHs+d9N~ zJk5K!9TB(2y|NDvz)KdSS06CxTdgWpOzcA83pz%w%>4|?lANorx=t|Nlr6_E3rTN6 zg^R5={;>K3b?!c!_&3x!3$Ja6e*1CeffkJ!CgDQ#&QUw*!$VZ3!@-rS9O3tJ>1qpy zOWp|;#)!Ajjs6!KH<#wnaH^wU)e~w_Juzzz44p-9GPW&7(`DxxMm*VdR2DQ#HU~!X z%nRQ(DjGL&k_<<>hBzX-{(Alz(_(J;LC+{H{`ZPwdTEkB{x%R_f%FQ{O#~Cw>;sivh>Y z=f+B4PviQhmZha={<9}ndrJYxpYoilCzS)kG!c?x!3Es=7>`(cv`SotGA+7-5gqa& z>4jrz#$(2E(O=7kjC;B!Mo2ljwASnJWI7Ic} zt595}*mKh`w$DRHW35+|LaVHohoj77%?<@*e!fmuWi6ZAt43~D)0W8c?b0l;VdrqU zWWXpS@EO*$xShnBf^v#jS?+3%?HwwuYPqUPy3?Qh^wm7VHg!j1{Eu%n5u3-qpouGj zJr6mRX4MJ0n4ArW9UpCTF>p%U5z7dQWF}e`9}-W0Hly4=6GoEPb;jv{I|K9Cv8l-?zp;D*KuylueV?0@kPjLeIQ zGVi~+KI)%^k2bqI>$YMX0)E;+5aepeeN*LvjVFr1X7=?dKsNaoYK;A{)<6vH@QpJd z#A4U=(5Td{ONLriA&Jj|Ly856PKw&P-l=4|VftkEl)E=Y&{?SlHB>I{Cmh}=1Oour zl$rs|-h8&+&5?Hu20*ak`>2F3)Y>gTum`xeE=SBuutMA)yP`P8UeDIBP4&3FF>$S@ zpu82e@hZElg<5%YA)XU^YhUqJ?>8%oLj|y+{|%3cy1n6389UuBGcR!|KVV5((jX2z4JI*A=u=L)m7nIURuv$zd-9@MY5n`(yLossO>+gQW>IM>~HP= zq)Mp>s@fjcUVkqExfM2d1t}wkBty^lVgZ!$6b0w3vE}TPxxT8j+TBmO1nAVVmed;H zlFgi$X;^aSh^w}eR?(|sU)l`Sr@X5vPC>h)Dt2EKC<{IpgH4r3E^$Z;o&D!u+pCSw zWZ2_P>*@TZ*aN^ed}HME9Q$};d{}s%^QZL5dmK%cpqb_AzC{HP-so$=Fu2}fV3E8vktI`b*_&`AJ&+om6fH&H zeo;3&O>NoUEIe9YO?LOA%3pBufo^?tJ+C?4%n8$fWHqb4gvGAhEo;$lwwRqxCERd1 zY{Pvy#-XLe_pH5IrH=UCd@Qc$eEzJ%BFH%8v}Nh*B|s*=1n}E$waSwpsjn*?p_CG818djn1VU$t35SS@;qfIIJ$G*F@|FLINh-kl{ za+;DlpG|gok(PQ-y<-JGnR2K>L#)1bGi3c69KSngdjjzx@|Ji6jiw54DYT0Guo87q z5%uiCPtV?)l}#&r$tQ(g%}dvL^~R!*B8}#b-o<>=k*tJoBjJ=Z`VeOGMKF9fN(7J|lZVAp^x@NQm7d> zQmrRl2;{DvUR~u zPgST*iZWKtfh#Cr+oSdo<5zo8;Vp>gkr^2kwKC_=_5$Yb88ft~V`oCM3uh7=Z?V)t zZ^NsfPvh@Gr|)G~V0HE1;ah>&RTgR#SR`;)#C|rERP`9C08VZd|71a7ch$~+)1Tg0 z(_cHC;qaqyK<|QUgl6L(aw3rVk^=`I0v9GKG@&bWdQ$jvFS01h#?=kmayBumEP(!e zCpI6p9MLL{3OuLD!*!}-`W&J!00#hSh^~&b%nZ@=Q#34&{}x^Q-zca*u7>WK+Mj|{1TtKH3L7a2q48gVuuG(7rFb7D zjA*ujKm_Y5x&K4x>wgZ2{ST=`$>}NoU{J{lNN~e4fAghT9cUomzRUC`v*-4gGpc@v zpI4L1QR6fu|KL%XpcPDYG|K269*#f0-v!;}^sV6q${sW8F0K@&0cRGoo!%+~;aqba>?EY^Skp z2Xgd&pZO|m;vBER(SkyL%aH-x#jA1)S#5^(JPp zLHC%`#b;ive^tK|Wm$!kVCKfkQAK2g8mYii5A~(80!#wWEU!EW&kP=+F&XmZ6xKb8 zIx4IqA%J(G8Jh3B2vRvhz*ReoWgj5y9E3F{JXSy^2jq4yWK zF?m2qiQ;tw(dpUw*06?2lho^^7a{v6p(u|0^W@4ZUDH(Z{N-owLXBR$>43jXGioHA zU>s6OEm3;0?7%&+^4hYm9DggqS-Jjb(b0HF$riQ;BG8l|uaXWMaO&oW!j3M@odHOB z@EIA$^&xA|VNW2cJ+`naN#65&H42g1_%c;6&h5EJ41$(!>(NeM1pfRJa6kDasrRr3-Jqck3TlbX3 z9eHviLP8y@CaOo5@5q%a1M95$4ZLfxwk#y{Pqw=*;n3!g->MN;Fe>o%W2 zvDiTU^{gg{={XgqHRXeYTyeU_Piew4mJeQW2ZHZ!eE{ozJ)t!V;n!9++u}KIf(q@# za-qMDIKUWYJ@gReD)fX$Qk-ZU*y^ICzmr0FFXIz|Knkts0Qn9|2e<>@LU5FA@RjBx zw2xST5&-ygKtKFX_tgHyjfBov z^E#5p3547CSjxQafaST#4c;A{+`jgw<2+hqxXWQs_Nh@*r>6^kr8^M*q{J4(CI^&- zNZ7R!8RExicWbFLw7PMZCz(Ae;MmIg6wD1=YJhrrw100}ek(*bzP&8ZO%>ZN+i}_j z*Ad;;lt*74?ys~)?Nsi>qSoY{VZAOXH3QE*(o(IGu5aL%`g5uap=}#oyDBsE0md!a zv*1b;4~)st38S4J|FlI}&2Xyabw}UQz`(wHH5Cu(LgjnvAM3RdGVvamy-V(kM!ywF z5%F?lE5DMPWO)Q77J5AleJm>E^|_-$YjMi`$6^M&XSQaG3-w?2C|YGXxom{QyJq~t ztJ^>;8#)u)b$Gg+cWO=rZPG3s59{XKJa>#cu4`OQw8Lghw+FvxsNXvk{=Ztewx}cz z09?tmO#!!Ac2Oz~kF&E*x>_g(Wm&V5re|n`RxUGjf?^?pD5o&>l&FQKhrHG~wN9ud z37QCYw7^QEyioq4B8nH(xQyFCnZ531FMIzUzNhbd_$~*MV!qI&^kr|WA-gF#b~|0P zElFHF!R3KF8LOM>#d6zDHU+qVFI|ijMw-N>baCt@v1eflQNANP)844jIRps|dbbkk zUj6dWzP^6Sh50bQ{5Y$8A_K~NgqZT z%~bP?K%OekyC2cCKSRvY+91{GPHZ3nUx@}dm8V|%-gGv=)4brPj4h$kr_!)teB=MymE@-P?tHXM83x++i)2)+|sD zF!@PuzJ(4io~C~&DoFYhH};x>ue$p#S|Ysoq=U9?u)CKsMFgTF;=Xoa078#diOYC< z!G8{`!+S8Wn7nh#Psa!JkC5)Ml19cg|r8|9&8Gi=`M}sxhw^h)h0~{r?4`@gSAAJ&h6c$YEw_LtI)uF{`&Q> z_xqvM9^;@=-d#9Mnxl%C(EA*=-pZxkW(VyyerkFXHk9MVjt|D6rl~?MK{EKI{ol0&Q|#hS}}u|79-v&t`+SUQks}4;+&=xy36(8y3$OlZx%C`6h#e?wsh0)GnpXLA-$V23m y9!|=_gPqnKtUA0JbNp*c^`8mB{|#WyI@T8X$v>h~nooSWABzab9BB$Wf9)TcR+m8l diff --git a/docs/source/tutorials/arch_modeling/figures/spyadder_waveform.png b/docs/source/tutorials/arch_modeling/figures/spyadder_waveform.png index 54e34a0017aca99e753ae12fdfae1b6b92b48285..d1fcda277d6fed2f8f677c620e145f537dd085a7 100644 GIT binary patch literal 11849 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 diff --git a/docs/source/tutorials/arch_modeling/figures/spypad_waveforms.png b/docs/source/tutorials/arch_modeling/figures/spypad_waveforms.png index 4ea110f599f9cf9f40dc908f6fbaa21f0febf7b2..948473e2c7af48fef1cc9801247a984cdb833d9a 100644 GIT binary patch literal 21301 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 literal 24078 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 z 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 Date: Mon, 12 Apr 2021 18:10:36 -0600 Subject: [PATCH 117/352] Provide more explanation in Pre-Built Spypads --- docs/source/tutorials/arch_modeling/spypads_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 1cbbeafe4..16b5d81c7 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -35,7 +35,7 @@ file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_op emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml -The spypads are defined from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172** +In this architecture file, the output ports of a 6-input Look Up Table (LUT) are defined as spypads using the XML syntax ``is_global`` and ``is_io``. As a result, all of the outputs from the 6-input LUT will be visible in the top-level module. The output ports to the 6-input LUT are declared from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172**. .. code-block:: xml From eff784e77b1fc1e4c9eb73ff167bef161d7a8d7b Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 13 Apr 2021 15:53:51 -0600 Subject: [PATCH 118/352] Upload new figures for spypad tutorial --- .../tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg | 1 + .../tutorials/arch_modeling/figures/lut6_Example_Spypad.svg | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg create mode 100644 docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg diff --git a/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg b/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg new file mode 100644 index 000000000..93f9801ac --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg b/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg new file mode 100644 index 000000000..1f2e8da11 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg @@ -0,0 +1 @@ + \ No newline at end of file From 423d814730adcba59c1b1c34692e61d83ebd4f84 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 13 Apr 2021 16:04:20 -0600 Subject: [PATCH 119/352] Update to include new figures --- .../tutorials/arch_modeling/spypads_tutorial.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 16b5d81c7..8683054ab 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -213,10 +213,10 @@ Using :ref:`fig_gpout_ports` as a guide, we can relate our task like :numref:`fi .. _fig_gpout_example: -.. figure:: ./figures/gpout_ports_example.png +.. figure:: ./figures/lut6_Example_Spypad.svg :scale: 100% - Diagram for ``lut6_out`` + Diagram for ``frac_lut6_spypad`` We can view testbench waveforms with GTKWave by running the following command from the root directory: @@ -302,6 +302,15 @@ The ``fpga_top.v`` should have the following in its module definition: input [0:0] clk; //----- GPOUT PORTS ----- output [0:19] gfpga_pad_ADDF_sumout; + +The architecture will now look like :numref:`fig_addf_example` + +.. _fig_addf_example: + +.. figure:: ./figures/ADDF_Example_Spypad.svg + :scale: 100% + + Diagram for ``ADDF`` We can view the waveform by running GTKWave: From 221822f0f02db199eb3594a835f25c39dc154f10 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:33:01 -0600 Subject: [PATCH 120/352] update figures to correctly display out ports --- .../tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg | 2 +- .../tutorials/arch_modeling/figures/lut6_Example_Spypad.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg b/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg index 93f9801ac..4d5affee6 100644 --- a/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg +++ b/docs/source/tutorials/arch_modeling/figures/ADDF_Example_Spypad.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg b/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg index 1f2e8da11..a82cd267b 100644 --- a/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg +++ b/docs/source/tutorials/arch_modeling/figures/lut6_Example_Spypad.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 410c6a12ff4b11b0af4c404c511cdcb5a3c06b4a Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:46:12 -0600 Subject: [PATCH 121/352] Update figures to be more accurate and clean --- .../tutorials/arch_modeling/spypads_tutorial.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 8683054ab..973a41f9f 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -72,7 +72,6 @@ The file will look like this when finished: .. code-block:: python :linenos: - :emphasize-lines: 44 # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # Configuration file for running experiments @@ -117,7 +116,7 @@ The file will look like this when finished: [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= - #vpr_fpga_verilog_formal_verification_top_netlist= + #LINE44 vpr_fpga_verilog_formal_verification_top_netlist= Our OpenFPGA task will now run the full testbench. We run the task with the following command from the root directory of OpenFPGA: @@ -216,7 +215,7 @@ Using :ref:`fig_gpout_ports` as a guide, we can relate our task like :numref:`fi .. figure:: ./figures/lut6_Example_Spypad.svg :scale: 100% - Diagram for ``frac_lut6_spypad`` + An illustrative example of the ``lut6`` spypad sourced from inside a logic element. We can view testbench waveforms with GTKWave by running the following command from the root directory: @@ -232,9 +231,9 @@ The waveforms will appear similar to :numref:`fig_spypad_waves` .. _fig_spypad_waves: .. figure:: ./figures/spypad_waveforms.png - :scale: 100% + :width: 75% - Spypad Waveforms + Waveforms of ``frac_lut6`` Spypads Building Spypads ~~~~~~~~~~~~~~~~ @@ -310,7 +309,7 @@ The architecture will now look like :numref:`fig_addf_example` .. figure:: ./figures/ADDF_Example_Spypad.svg :scale: 100% - Diagram for ``ADDF`` + An illustrative example of the sumout spypad sourced from an adder inside a logic element. There are 10 logic elements in a CLB, and we are looking at the 1st logic element. We can view the waveform by running GTKWave: @@ -325,7 +324,7 @@ The waveform should have some changes to its value. An example of what it may lo .. figure:: ./figures/spyadder_waveform.png :scale: 100% - Sumout Waveform + Waveforms of ``sumout`` Spypad Conclusion ~~~~~~~~~~ From 86ad57253074d0b8050bd51f73a04a476c8cd389 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 14:27:54 -0600 Subject: [PATCH 122/352] [Benchmark] Add opencore RTLs from IWLS 2005 benchmarks --- .../benchmarks/iwls2005/ac97_ctrl/ac97_cra.v | 196 + .../iwls2005/ac97_ctrl/ac97_defines.v | 173 + .../iwls2005/ac97_ctrl/ac97_dma_if.v | 220 + .../iwls2005/ac97_ctrl/ac97_dma_req.v | 119 + .../iwls2005/ac97_ctrl/ac97_fifo_ctrl.v | 117 + .../iwls2005/ac97_ctrl/ac97_in_fifo.v | 342 ++ .../benchmarks/iwls2005/ac97_ctrl/ac97_int.v | 126 + .../iwls2005/ac97_ctrl/ac97_out_fifo.v | 348 ++ .../benchmarks/iwls2005/ac97_ctrl/ac97_prc.v | 336 ++ .../benchmarks/iwls2005/ac97_ctrl/ac97_rf.v | 306 ++ .../benchmarks/iwls2005/ac97_ctrl/ac97_rst.v | 103 + .../benchmarks/iwls2005/ac97_ctrl/ac97_sin.v | 145 + .../benchmarks/iwls2005/ac97_ctrl/ac97_soc.v | 205 + .../benchmarks/iwls2005/ac97_ctrl/ac97_sout.v | 183 + .../benchmarks/iwls2005/ac97_ctrl/ac97_top.v | 761 +++ .../iwls2005/ac97_ctrl/ac97_wb_if.v | 204 + .../iwls2005/aes_core/aes_cipher_top.v | 256 + .../iwls2005/aes_core/aes_inv_cipher_top.v | 327 ++ .../iwls2005/aes_core/aes_inv_sbox.v | 328 ++ .../iwls2005/aes_core/aes_key_expand_128.v | 87 + .../benchmarks/iwls2005/aes_core/aes_rcon.v | 96 + .../benchmarks/iwls2005/aes_core/aes_sbox.v | 329 ++ .../benchmarks/iwls2005/aes_core/timescale.v | 1 + .../benchmarks/iwls2005/des/README.txt | 145 + .../benchmarks/iwls2005/des/area_opt/des.v | 95 + .../benchmarks/iwls2005/des/area_opt/des3.v | 148 + .../iwls2005/des/area_opt/key_sel.v | 464 ++ .../iwls2005/des/area_opt/key_sel3.v | 865 +++ .../benchmarks/iwls2005/des/common/crp.v | 69 + .../benchmarks/iwls2005/des/common/sbox1.v | 113 + .../benchmarks/iwls2005/des/common/sbox2.v | 113 + .../benchmarks/iwls2005/des/common/sbox3.v | 113 + .../benchmarks/iwls2005/des/common/sbox4.v | 113 + .../benchmarks/iwls2005/des/common/sbox5.v | 113 + .../benchmarks/iwls2005/des/common/sbox6.v | 113 + .../benchmarks/iwls2005/des/common/sbox7.v | 113 + .../benchmarks/iwls2005/des/common/sbox8.v | 113 + .../benchmarks/iwls2005/des/perf_opt/des.v | 236 + .../benchmarks/iwls2005/des/perf_opt/des3.v | 79 + .../iwls2005/des/perf_opt/key_sel.v | 852 +++ .../iwls2005/ethernet/eth_clockgen.v | 134 + .../benchmarks/iwls2005/ethernet/eth_cop.v | 392 ++ .../benchmarks/iwls2005/ethernet/eth_crc.v | 148 + .../iwls2005/ethernet/eth_defines.v | 348 ++ .../benchmarks/iwls2005/ethernet/eth_fifo.v | 189 + .../iwls2005/ethernet/eth_maccontrol.v | 274 + .../iwls2005/ethernet/eth_macstatus.v | 428 ++ .../benchmarks/iwls2005/ethernet/eth_miim.v | 451 ++ .../iwls2005/ethernet/eth_outputcontrol.v | 150 + .../benchmarks/iwls2005/ethernet/eth_random.v | 144 + .../iwls2005/ethernet/eth_receivecontrol.v | 441 ++ .../iwls2005/ethernet/eth_register.v | 111 + .../iwls2005/ethernet/eth_registers.v | 1184 ++++ .../iwls2005/ethernet/eth_rxaddrcheck.v | 211 + .../iwls2005/ethernet/eth_rxcounters.v | 221 + .../iwls2005/ethernet/eth_rxethmac.v | 380 ++ .../iwls2005/ethernet/eth_rxstatem.v | 200 + .../iwls2005/ethernet/eth_shiftreg.v | 154 + .../iwls2005/ethernet/eth_spram_256x32.v | 312 ++ .../benchmarks/iwls2005/ethernet/eth_top.v | 971 ++++ .../iwls2005/ethernet/eth_transmitcontrol.v | 330 ++ .../iwls2005/ethernet/eth_txcounters.v | 224 + .../iwls2005/ethernet/eth_txethmac.v | 495 ++ .../iwls2005/ethernet/eth_txstatem.v | 287 + .../iwls2005/ethernet/eth_wishbone.v | 2559 +++++++++ .../benchmarks/iwls2005/ethernet/timescale.v | 53 + .../iwls2005/ethernet/xilinx_dist_ram_16x32.v | 50 + .../benchmarks/iwls2005/fpu/except.v | 153 + openfpga_flow/benchmarks/iwls2005/fpu/fpu.v | 560 ++ .../benchmarks/iwls2005/fpu/post_norm.v | 676 +++ .../benchmarks/iwls2005/fpu/pre_norm.v | 270 + .../benchmarks/iwls2005/fpu/pre_norm_fmul.v | 150 + .../benchmarks/iwls2005/fpu/primitives.v | 103 + .../iwls2005/i2c/i2c_master_bit_ctrl.v | 535 ++ .../iwls2005/i2c/i2c_master_byte_ctrl.v | 344 ++ .../iwls2005/i2c/i2c_master_defines.v | 64 + .../benchmarks/iwls2005/i2c/i2c_master_top.v | 301 ++ .../benchmarks/iwls2005/i2c/timescale.v | 2 + .../benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v | 290 + .../benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v | 276 + .../benchmarks/iwls2005/mem_ctrl/mc_defines.v | 232 + .../benchmarks/iwls2005/mem_ctrl/mc_dp.v | 244 + .../benchmarks/iwls2005/mem_ctrl/mc_incn_r.v | 102 + .../benchmarks/iwls2005/mem_ctrl/mc_mem_if.v | 362 ++ .../benchmarks/iwls2005/mem_ctrl/mc_obct.v | 236 + .../iwls2005/mem_ctrl/mc_obct_top.v | 426 ++ .../benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v | 130 + .../benchmarks/iwls2005/mem_ctrl/mc_refresh.v | 210 + .../benchmarks/iwls2005/mem_ctrl/mc_rf.v | 836 +++ .../benchmarks/iwls2005/mem_ctrl/mc_timing.v | 1735 ++++++ .../benchmarks/iwls2005/mem_ctrl/mc_top.v | 549 ++ .../benchmarks/iwls2005/mem_ctrl/mc_wb_if.v | 252 + .../benchmarks/iwls2005/pci/bus_commands.v | 80 + .../iwls2005/pci/pci_async_reset_flop.v | 102 + .../benchmarks/iwls2005/pci/pci_bridge32.v | 1653 ++++++ .../benchmarks/iwls2005/pci/pci_cbe_en_crit.v | 85 + .../iwls2005/pci/pci_conf_cyc_addr_dec.v | 119 + .../benchmarks/iwls2005/pci/pci_conf_space.v | 3932 ++++++++++++++ .../benchmarks/iwls2005/pci/pci_constants.v | 170 + .../benchmarks/iwls2005/pci/pci_cur_out_reg.v | 271 + .../iwls2005/pci/pci_delayed_sync.v | 469 ++ .../iwls2005/pci/pci_delayed_write_reg.v | 95 + .../benchmarks/iwls2005/pci/pci_frame_crit.v | 83 + .../iwls2005/pci/pci_frame_en_crit.v | 85 + .../iwls2005/pci/pci_frame_load_crit.v | 84 + .../benchmarks/iwls2005/pci/pci_in_reg.v | 160 + .../benchmarks/iwls2005/pci/pci_io_mux.v | 855 +++ .../iwls2005/pci/pci_io_mux_ad_en_crit.v | 75 + .../iwls2005/pci/pci_io_mux_ad_load_crit.v | 77 + .../iwls2005/pci/pci_irdy_out_crit.v | 85 + .../iwls2005/pci/pci_mas_ad_en_crit.v | 82 + .../iwls2005/pci/pci_mas_ad_load_crit.v | 70 + .../iwls2005/pci/pci_mas_ch_state_crit.v | 85 + .../benchmarks/iwls2005/pci/pci_master32_sm.v | 615 +++ .../iwls2005/pci/pci_master32_sm_if.v | 846 +++ .../benchmarks/iwls2005/pci/pci_out_reg.v | 124 + .../benchmarks/iwls2005/pci/pci_par_crit.v | 90 + .../iwls2005/pci/pci_parity_check.v | 336 ++ .../benchmarks/iwls2005/pci/pci_pci_decoder.v | 201 + .../benchmarks/iwls2005/pci/pci_pci_tpram.v | 464 ++ .../iwls2005/pci/pci_pcir_fifo_control.v | 336 ++ .../iwls2005/pci/pci_pciw_fifo_control.v | 323 ++ .../iwls2005/pci/pci_pciw_pcir_fifos.v | 628 +++ .../benchmarks/iwls2005/pci/pci_perr_crit.v | 90 + .../iwls2005/pci/pci_perr_en_crit.v | 106 + .../benchmarks/iwls2005/pci/pci_ram_16x40d.v | 99 + .../benchmarks/iwls2005/pci/pci_rst_int.v | 171 + .../benchmarks/iwls2005/pci/pci_serr_crit.v | 87 + .../iwls2005/pci/pci_serr_en_crit.v | 87 + .../benchmarks/iwls2005/pci/pci_spoci_ctrl.v | 916 ++++ .../benchmarks/iwls2005/pci/pci_sync_module.v | 167 + .../iwls2005/pci/pci_synchronizer_flop.v | 103 + .../iwls2005/pci/pci_target32_clk_en.v | 104 + .../iwls2005/pci/pci_target32_devs_crit.v | 89 + .../iwls2005/pci/pci_target32_interface.v | 962 ++++ .../benchmarks/iwls2005/pci/pci_target32_sm.v | 758 +++ .../iwls2005/pci/pci_target32_stop_crit.v | 89 + .../iwls2005/pci/pci_target32_trdy_crit.v | 89 + .../benchmarks/iwls2005/pci/pci_target_unit.v | 946 ++++ .../iwls2005/pci/pci_user_constants.v | 330 ++ .../benchmarks/iwls2005/pci/pci_wb_addr_mux.v | 279 + .../benchmarks/iwls2005/pci/pci_wb_decoder.v | 170 + .../benchmarks/iwls2005/pci/pci_wb_master.v | 1173 ++++ .../benchmarks/iwls2005/pci/pci_wb_slave.v | 1147 ++++ .../iwls2005/pci/pci_wb_slave_unit.v | 876 +++ .../benchmarks/iwls2005/pci/pci_wb_tpram.v | 465 ++ .../iwls2005/pci/pci_wbr_fifo_control.v | 270 + .../iwls2005/pci/pci_wbs_wbb3_2_wbb2.v | 281 + .../iwls2005/pci/pci_wbw_fifo_control.v | 300 + .../iwls2005/pci/pci_wbw_wbr_fifos.v | 599 ++ .../benchmarks/iwls2005/pci/timescale.v | 19 + .../benchmarks/iwls2005/sasc/sasc_brg.v | 160 + .../benchmarks/iwls2005/sasc/sasc_fifo4.v | 135 + .../benchmarks/iwls2005/sasc/sasc_top.v | 301 ++ .../benchmarks/iwls2005/sasc/timescale.v | 1 + .../benchmarks/iwls2005/simple_spi/fifo4.v | 134 + .../iwls2005/simple_spi/simple_spi_top.v | 329 ++ .../benchmarks/iwls2005/spi/spi_clgen.v | 108 + .../benchmarks/iwls2005/spi/spi_defines.v | 159 + .../benchmarks/iwls2005/spi/spi_shift.v | 238 + .../benchmarks/iwls2005/spi/spi_top.v | 287 + .../benchmarks/iwls2005/spi/timescale.v | 2 + .../benchmarks/iwls2005/ss_pcm/pcm_slv_top.v | 222 + .../benchmarks/iwls2005/ss_pcm/timescale.v | 1 + .../steppermotordrive/StepperMotorDrive.vhd | 139 + .../benchmarks/iwls2005/systemcaes/aes.v | 358 ++ .../iwls2005/systemcaes/byte_mixcolum.v | 92 + .../benchmarks/iwls2005/systemcaes/keysched.v | 248 + .../benchmarks/iwls2005/systemcaes/mixcolum.v | 188 + .../benchmarks/iwls2005/systemcaes/sbox.v | 392 ++ .../benchmarks/iwls2005/systemcaes/subbytes.v | 254 + .../iwls2005/systemcaes/timescale.v | 1 + .../iwls2005/systemcaes/word_mixcolum.v | 124 + .../benchmarks/iwls2005/systemcdes/des.v | 284 + .../benchmarks/iwls2005/systemcdes/desround.v | 223 + .../benchmarks/iwls2005/systemcdes/key_gen.v | 192 + .../benchmarks/iwls2005/systemcdes/s1.v | 137 + .../benchmarks/iwls2005/systemcdes/s2.v | 137 + .../benchmarks/iwls2005/systemcdes/s3.v | 138 + .../benchmarks/iwls2005/systemcdes/s4.v | 138 + .../benchmarks/iwls2005/systemcdes/s5.v | 139 + .../benchmarks/iwls2005/systemcdes/s6.v | 139 + .../benchmarks/iwls2005/systemcdes/s7.v | 138 + .../benchmarks/iwls2005/systemcdes/s8.v | 137 + .../benchmarks/iwls2005/tv80/tv80_alu.v | 442 ++ .../benchmarks/iwls2005/tv80/tv80_core.v | 1304 +++++ .../benchmarks/iwls2005/tv80/tv80_mcode.v | 2759 ++++++++++ .../benchmarks/iwls2005/tv80/tv80_reg.v | 71 + .../benchmarks/iwls2005/tv80/tv80s.v | 160 + .../iwls2005/usb_funct/usbf_crc16.v | 115 + .../benchmarks/iwls2005/usb_funct/usbf_crc5.v | 106 + .../iwls2005/usb_funct/usbf_defines.v | 294 + .../iwls2005/usb_funct/usbf_ep_rf.v | 516 ++ .../iwls2005/usb_funct/usbf_ep_rf_dummy.v | 152 + .../benchmarks/iwls2005/usb_funct/usbf_idma.v | 636 +++ .../iwls2005/usb_funct/usbf_mem_arb.v | 196 + .../benchmarks/iwls2005/usb_funct/usbf_pa.v | 386 ++ .../benchmarks/iwls2005/usb_funct/usbf_pd.v | 437 ++ .../benchmarks/iwls2005/usb_funct/usbf_pe.v | 1095 ++++ .../benchmarks/iwls2005/usb_funct/usbf_pl.v | 483 ++ .../benchmarks/iwls2005/usb_funct/usbf_rf.v | 1909 +++++++ .../benchmarks/iwls2005/usb_funct/usbf_top.v | 622 +++ .../iwls2005/usb_funct/usbf_utmi_if.v | 258 + .../iwls2005/usb_funct/usbf_utmi_ls.v | 654 +++ .../benchmarks/iwls2005/usb_funct/usbf_wb.v | 282 + .../benchmarks/iwls2005/usb_phy/timescale.v | 1 + .../benchmarks/iwls2005/usb_phy/usb_phy.v | 184 + .../benchmarks/iwls2005/usb_phy/usb_rx_phy.v | 452 ++ .../benchmarks/iwls2005/usb_phy/usb_tx_phy.v | 465 ++ .../iwls2005/vga_lcd/generic_dpram.v | 515 ++ .../iwls2005/vga_lcd/generic_spram.v | 410 ++ .../benchmarks/iwls2005/vga_lcd/timescale.v | 2 + .../benchmarks/iwls2005/vga_lcd/vga_clkgen.v | 138 + .../benchmarks/iwls2005/vga_lcd/vga_colproc.v | 510 ++ .../benchmarks/iwls2005/vga_lcd/vga_csm_pb.v | 156 + .../iwls2005/vga_lcd/vga_cur_cregs.v | 140 + .../benchmarks/iwls2005/vga_lcd/vga_curproc.v | 314 ++ .../benchmarks/iwls2005/vga_lcd/vga_defines.v | 102 + .../benchmarks/iwls2005/vga_lcd/vga_enh_top.v | 448 ++ .../benchmarks/iwls2005/vga_lcd/vga_fifo.v | 259 + .../benchmarks/iwls2005/vga_lcd/vga_fifo_dc.v | 234 + .../benchmarks/iwls2005/vga_lcd/vga_pgen.v | 591 ++ .../benchmarks/iwls2005/vga_lcd/vga_tgen.v | 144 + .../benchmarks/iwls2005/vga_lcd/vga_vtim.v | 179 + .../iwls2005/vga_lcd/vga_wb_master.v | 471 ++ .../iwls2005/vga_lcd/vga_wb_slave.v | 465 ++ .../iwls2005/wb_conmax/wb_conmax_arb.v | 267 + .../iwls2005/wb_conmax/wb_conmax_defines.v | 65 + .../iwls2005/wb_conmax/wb_conmax_master_if.v | 659 +++ .../iwls2005/wb_conmax/wb_conmax_msel.v | 246 + .../iwls2005/wb_conmax/wb_conmax_pri_dec.v | 119 + .../iwls2005/wb_conmax/wb_conmax_pri_enc.v | 186 + .../iwls2005/wb_conmax/wb_conmax_rf.v | 311 ++ .../iwls2005/wb_conmax/wb_conmax_slave_if.v | 449 ++ .../iwls2005/wb_conmax/wb_conmax_top.v | 4806 +++++++++++++++++ .../iwls2005/wb_dma/wb_dma_ch_arb.v | 2157 ++++++++ .../iwls2005/wb_dma/wb_dma_ch_pri_enc.v | 384 ++ .../benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v | 587 ++ .../iwls2005/wb_dma/wb_dma_ch_sel.v | 1392 +++++ .../benchmarks/iwls2005/wb_dma/wb_dma_de.v | 632 +++ .../iwls2005/wb_dma/wb_dma_defines.v | 120 + .../iwls2005/wb_dma/wb_dma_inc30r.v | 96 + .../iwls2005/wb_dma/wb_dma_pri_enc_sub.v | 146 + .../benchmarks/iwls2005/wb_dma/wb_dma_rf.v | 1860 +++++++ .../benchmarks/iwls2005/wb_dma/wb_dma_top.v | 1126 ++++ .../benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v | 223 + .../iwls2005/wb_dma/wb_dma_wb_mast.v | 170 + .../iwls2005/wb_dma/wb_dma_wb_slv.v | 180 + 248 files changed, 93409 insertions(+) create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v create mode 100644 openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/README.txt create mode 100644 openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/crp.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/except.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/fpu.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/post_norm.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v create mode 100644 openfpga_flow/benchmarks/iwls2005/fpu/primitives.v create mode 100644 openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v create mode 100644 openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v create mode 100644 openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/i2c/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_pcir_fifo_control.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_fifo_control.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_pcir_fifos.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_perr_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_perr_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_ram_16x40d.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_rst_int.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_serr_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_serr_en_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_spoci_ctrl.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wbr_fifo_control.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wbs_wbb3_2_wbb2.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_fifo_control.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_wbr_fifos.v create mode 100644 openfpga_flow/benchmarks/iwls2005/pci/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/sasc/sasc_brg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/sasc/sasc_fifo4.v create mode 100644 openfpga_flow/benchmarks/iwls2005/sasc/sasc_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/sasc/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/simple_spi/fifo4.v create mode 100644 openfpga_flow/benchmarks/iwls2005/simple_spi/simple_spi_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/spi/spi_clgen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/spi/spi_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/spi/spi_shift.v create mode 100644 openfpga_flow/benchmarks/iwls2005/spi/spi_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/spi/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ss_pcm/pcm_slv_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/ss_pcm/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/steppermotordrive/StepperMotorDrive.vhd create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/des.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v create mode 100644 openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v create mode 100644 openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v create mode 100644 openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v create mode 100644 openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v create mode 100644 openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v create mode 100644 openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_ls.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v create mode 100644 openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_spram.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/timescale.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_clkgen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_colproc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_csm_pb.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_cur_cregs.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_curproc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo_dc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_pgen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_tgen.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_vtim.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_master.v create mode 100644 openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v create mode 100644 openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v new file mode 100644 index 000000000..66a4226bd --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v @@ -0,0 +1,196 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Codec Register Access Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +// CVS Log +// +// $Id: ac97_cra.v,v 1.3 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_cra.v,v $ +// Revision 1.3 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:49 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:18 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_cra(clk, rst, + + crac_we, crac_din, crac_out, + crac_wr_done, crac_rd_done, + + valid, out_slt1, out_slt2, + in_slt2, + + crac_valid, crac_wr + ); + +input clk, rst; +input crac_we; +output [15:0] crac_din; +input [31:0] crac_out; +output crac_wr_done, crac_rd_done; + +input valid; +output [19:0] out_slt1; +output [19:0] out_slt2; +input [19:0] in_slt2; + +output crac_valid; +output crac_wr; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg crac_wr; +reg crac_rd; +reg crac_rd_done; +reg [15:0] crac_din; +reg crac_we_r; +reg valid_r; +wire valid_ne; +wire valid_pe; +reg rdd1, rdd2, rdd3; + +//////////////////////////////////////////////////////////////////// +// +// Codec Register Data Path +// + +// Control +assign out_slt1[19] = crac_out[31]; +assign out_slt1[18:12] = crac_out[22:16]; +assign out_slt1[11:0] = 12'h0; + +// Write Data +assign out_slt2[19:4] = crac_out[15:0]; +assign out_slt2[3:0] = 4'h0; + +// Read Data +always @(posedge clk or negedge rst) + begin + if(!rst) crac_din <= #1 16'h0; + else + if(crac_rd_done) crac_din <= #1 in_slt2[19:4]; + end + +//////////////////////////////////////////////////////////////////// +// +// Codec Register Access Tracking +// + +assign crac_valid = crac_wr | crac_rd; + +always @(posedge clk) + crac_we_r <= #1 crac_we; + +always @(posedge clk or negedge rst) + if(!rst) crac_wr <= #1 1'b0; + else + if(crac_we_r & !crac_out[31]) crac_wr <= #1 1'b1; + else + if(valid_ne) crac_wr <= #1 1'b0; + +assign crac_wr_done = crac_wr & valid_ne; + +always @(posedge clk or negedge rst) + if(!rst) crac_rd <= #1 1'b0; + else + if(crac_we_r & crac_out[31]) crac_rd <= #1 1'b1; + else + if(rdd1 & valid_pe) crac_rd <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) rdd1 <= #1 1'b0; + else + if(crac_rd & valid_ne) rdd1 <= #1 1'b1; + else + if(!crac_rd) rdd1 <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) rdd2 <= #1 1'b0; + else + if( (crac_rd & valid_ne) | (!rdd3 & rdd2) ) rdd2 <= #1 1'b1; + else + if(crac_rd_done) rdd2 <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) rdd3 <= #1 1'b0; + else + if(rdd2 & valid_pe) rdd3 <= #1 1'b1; + else + if(crac_rd_done) rdd3 <= #1 1'b0; + +always @(posedge clk) + crac_rd_done <= #1 rdd3 & valid_pe; + +always @(posedge clk) + valid_r <= #1 valid; + +assign valid_ne = !valid & valid_r; + +assign valid_pe = valid & !valid_r; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v new file mode 100644 index 000000000..7667c26a0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v @@ -0,0 +1,173 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller Definitions //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_defines.v,v 1.5 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_defines.v,v $ +// Revision 1.5 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.4 2002/03/11 03:21:22 rudi +// +// - Added defines to select fifo depth between 4, 8 and 16 entries. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:49 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:14 rudi +// Initial Checkin +// +// +// +// + +`timescale 1ns / 10ps + +///////////////////////////////////////////////////////////////////// +// This AC97 Controller supports up to 6 Output and 3 Input Channels. +// Comment out the define statement for which channels you do not wish +// to support in your implementation. The main Left and Right channels +// are always supported. + +// Surround Left + Right +`define AC97_SURROUND 1 + +// Center Channel +`define AC97_CENTER 1 + +// LFE Channel +`define AC97_LFE 1 + +// Stereo Input +`define AC97_SIN 1 + +// Mono Microphone Input +`define AC97_MICIN 1 + +///////////////////////////////////////////////////////////////////// +// +// This define selects how the WISHBONE interface determines if +// the internal register file is selected. +// This should be a simple address decoder. "wb_addr_i" is the +// WISHBONE address bus (32 bits wide). +`define AC97_REG_SEL (wb_addr_i[31:29] == 3'h0) + +///////////////////////////////////////////////////////////////////// +// +// This is a prescaler that generates a pulse every 250 nS. +// The value here should one less than the actually calculated +// value. +// For a 200 MHz wishbone clock, this value is 49 (50-1). +`define AC97_250_PS 6'h31 + +///////////////////////////////////////////////////////////////////// +// +// AC97 Cold reset Must be asserted for at least 1uS. The AC97 +// controller will stretch the reset pulse to at least 1uS. +// The reset timer is driven by the AC97_250_PS prescaler. +// This value should probably be never changed. Adjust the +// AC97_250_PS instead. +`define AC97_RST_DEL 3'h4 + +///////////////////////////////////////////////////////////////////// +// +// This value indicates for how long the resume signaling (asserting sync) +// should be done. This counter is driven by the AC97_250_PS prescaler. +// This value times 250nS is the duration of the resume signaling. +// The actual value must be incremented by one, as we do not know +// the current state of the prescaler, and must somehow insure we +// meet the minimum 1uS length. This value should probably be never +// changed. Modify the AC97_250_PS instead. +`define AC97_RES_SIG 3'h5 + +///////////////////////////////////////////////////////////////////// +// +// If the bit clock is absent for at least two "predicted" bit +// clock periods (163 nS) we should signal "suspended". +// This value defines how many WISHBONE cycles must pass without +// any change on the bit clock input before we signal "suspended". +// For a 200 MHz WISHBONE clock this would be about (163/5) 33 cycles. +`define AC97_SUSP_DET 6'h21 + +///////////////////////////////////////////////////////////////////// +// +// Select FIFO Depth. For most applications a FIFO depth of 4 should +// be sufficient. For systems with slow interrupt processing or slow +// DMA response or systems with low internal bus bandwidth you might +// want to increase the FIFO sizes to reduce the interrupt/DMA service +// request frequencies. +// Service request frequency can be calculated as follows: +// Channel bandwidth / FIFO size = Service Request Frequency +// For Example: 48KHz / 4 = 12 kHz +// +// Select Input FIFO depth by uncommenting ONE of the following define +// statements: +`define AC97_IN_FIFO_DEPTH_4 +//`define AC97_IN_FIFO_DEPTH_8 +//`define AC97_IN_FIFO_DEPTH_16 +// +// Select Output FIFO depth by uncommenting ONE of the following define +// statements: +`define AC97_OUT_FIFO_DEPTH_4 +//`define AC97_OUT_FIFO_DEPTH_8 +//`define AC97_OUT_FIFO_DEPTH_16 + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v new file mode 100644 index 000000000..da10b165e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v @@ -0,0 +1,220 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// DMA Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_dma_if.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_dma_if.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:49 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:18 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_dma_if(clk, rst, + o3_status, o4_status, o6_status, o7_status, o8_status, o9_status, + o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, o9_empty, + i3_status, i4_status, i6_status, + i3_full, i4_full, i6_full, + + oc0_cfg, oc1_cfg, oc2_cfg, oc3_cfg, oc4_cfg, oc5_cfg, + ic0_cfg, ic1_cfg, ic2_cfg, + + dma_req, dma_ack); + +input clk, rst; +input [1:0] o3_status, o4_status, o6_status, o7_status, o8_status, o9_status; +input o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, o9_empty; +input [1:0] i3_status, i4_status, i6_status; +input i3_full, i4_full, i6_full; +input [7:0] oc0_cfg; +input [7:0] oc1_cfg; +input [7:0] oc2_cfg; +input [7:0] oc3_cfg; +input [7:0] oc4_cfg; +input [7:0] oc5_cfg; +input [7:0] ic0_cfg; +input [7:0] ic1_cfg; +input [7:0] ic2_cfg; +output [8:0] dma_req; +input [8:0] dma_ack; + +//////////////////////////////////////////////////////////////////// +// +// DMA Request Modules +// + +ac97_dma_req u0(.clk( clk ), + .rst( rst ), + .cfg( oc0_cfg ), + .status( o3_status ), + .full_empty( o3_empty ), + .dma_req( dma_req[0] ), + .dma_ack( dma_ack[0] ) + ); + +ac97_dma_req u1(.clk( clk ), + .rst( rst ), + .cfg( oc1_cfg ), + .status( o4_status ), + .full_empty( o4_empty ), + .dma_req( dma_req[1] ), + .dma_ack( dma_ack[1] ) + ); + +`ifdef AC97_CENTER +ac97_dma_req u2(.clk( clk ), + .rst( rst ), + .cfg( oc2_cfg ), + .status( o6_status ), + .full_empty( o6_empty ), + .dma_req( dma_req[2] ), + .dma_ack( dma_ack[2] ) + ); +`else +assign dma_req[2] = 1'b0; +`endif + +`ifdef AC97_SURROUND +ac97_dma_req u3(.clk( clk ), + .rst( rst ), + .cfg( oc3_cfg ), + .status( o7_status ), + .full_empty( o7_empty ), + .dma_req( dma_req[3] ), + .dma_ack( dma_ack[3] ) + ); + +ac97_dma_req u4(.clk( clk ), + .rst( rst ), + .cfg( oc4_cfg ), + .status( o8_status ), + .full_empty( o8_empty ), + .dma_req( dma_req[4] ), + .dma_ack( dma_ack[4] ) + ); +`else +assign dma_req[3] = 1'b0; +assign dma_req[4] = 1'b0; +`endif + +`ifdef AC97_LFE +ac97_dma_req u5(.clk( clk ), + .rst( rst ), + .cfg( oc5_cfg ), + .status( o9_status ), + .full_empty( o9_empty ), + .dma_req( dma_req[5] ), + .dma_ack( dma_ack[5] ) + ); +`else +assign dma_req[5] = 1'b0; +`endif + +`ifdef AC97_SIN +ac97_dma_req u6(.clk( clk ), + .rst( rst ), + .cfg( ic0_cfg ), + .status( i3_status ), + .full_empty( i3_full ), + .dma_req( dma_req[6] ), + .dma_ack( dma_ack[6] ) + ); + +ac97_dma_req u7(.clk( clk ), + .rst( rst ), + .cfg( ic1_cfg ), + .status( i4_status ), + .full_empty( i4_full ), + .dma_req( dma_req[7] ), + .dma_ack( dma_ack[7] ) + ); +`else +assign dma_req[6] = 1'b0; +assign dma_req[7] = 1'b0; +`endif + +`ifdef AC97_MICIN +ac97_dma_req u8(.clk( clk ), + .rst( rst ), + .cfg( ic2_cfg ), + .status( i6_status ), + .full_empty( i6_full ), + .dma_req( dma_req[8] ), + .dma_ack( dma_ack[8] ) + ); +`else +assign dma_req[8] = 1'b0; +`endif + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v new file mode 100644 index 000000000..853dbefbf --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// DMA Request Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_dma_req.v,v 1.3 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_dma_req.v,v $ +// Revision 1.3 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:49 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:16 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_dma_req(clk, rst, cfg, status, full_empty, dma_req, dma_ack); +input clk, rst; +input [7:0] cfg; +input [1:0] status; +input full_empty; +output dma_req; +input dma_ack; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// +reg dma_req_d; +reg dma_req_r1; +reg dma_req; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(cfg or status or full_empty) + case(cfg[5:4]) // synopsys parallel_case full_case + // REQ = Ch_EN & DMA_EN & Status + // 1/4 full/empty + 2'h2: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status == 2'h0)); + // 1/2 full/empty + 2'h1: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status[1] == 1'h0)); + // 3/4 full/empty + 2'h0: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status < 2'h3)); + 2'h3: dma_req_d = cfg[0] & cfg[6] & full_empty; + endcase + +always @(posedge clk) + dma_req_r1 <= #1 dma_req_d & !dma_ack; + +always @(posedge clk or negedge rst) + if(!rst) dma_req <= #1 1'b0; + else + if(dma_req_r1 & dma_req_d & !dma_ack) dma_req <= #1 1'b1; + else + if(dma_ack) dma_req <= #1 1'b0; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v new file mode 100644 index 000000000..9db66a0f7 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// FIFO Control Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_fifo_ctrl.v,v 1.3 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_fifo_ctrl.v,v $ +// Revision 1.3 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:49 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:18 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_fifo_ctrl( clk, + valid, ch_en, srs, full_empty, req, crdy, + en_out, en_out_l + ); +input clk; +input valid; +input ch_en; // Channel Enable +input srs; // Sample Rate Select +input full_empty; // Fifo Status +input req; // Codec Request +input crdy; // Codec Ready +output en_out; // Output read/write pulse +output en_out_l; // Latched Output + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg en_out_l, en_out_l2; +reg full_empty_r; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + if(!valid) full_empty_r <= #1 full_empty; + +always @(posedge clk) + if(valid & ch_en & !full_empty_r & crdy & (!srs | (srs & req) ) ) + en_out_l <= #1 1'b1; + else + if(!valid & !(ch_en & !full_empty_r & crdy & (!srs | (srs & req) )) ) + en_out_l <= #1 1'b0; + +always @(posedge clk) + en_out_l2 <= #1 en_out_l & valid; + +assign en_out = en_out_l & !en_out_l2 & valid; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v new file mode 100644 index 000000000..e0710005d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v @@ -0,0 +1,342 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Output FIFO //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_in_fifo.v,v 1.5 2002/11/14 17:10:12 rudi Exp $ +// +// $Date: 2002/11/14 17:10:12 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_in_fifo.v,v $ +// Revision 1.5 2002/11/14 17:10:12 rudi +// Fixed a bug in the IN-FIFO - 18 bit samples where not alligned correctly. +// +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/11 03:21:22 rudi +// +// - Added defines to select fifo depth between 4, 8 and 16 entries. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:14 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +`ifdef AC97_IN_FIFO_DEPTH_4 + +// 4 entry deep verion of the input FIFO + +module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [19:0] din; +input we; +output [31:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:3]; +reg [31:0] dout; + +reg [3:0] wp; +reg [2:0] rp; + +wire [3:0] wp_p1; + +reg [1:0] status; +reg [15:0] din_tmp1; +reg [31:0] din_tmp; +wire m16b; +reg full, empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 4'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = m16b ? (wp + 4'h1) : (wp + 4'h2); + +always @(posedge clk) + if(!en) rp <= #1 3'h0; + else + if(re) rp <= #1 rp + 3'h1; + +always @(posedge clk) + status <= #1 ((rp[1:0] - wp[2:1]) - 2'h1); + +always @(posedge clk) + empty <= #1 (wp[3:1] == rp[2:0]) & (m16b ? !wp[0] : 1'b0); + +always @(posedge clk) + full <= #1 (wp[2:1] == rp[1:0]) & (wp[3] != rp[2]); + +// Fifo Output +always @(posedge clk) + dout <= #1 mem[ rp[1:0] ]; + +// Fifo Input Half Word Latch +always @(posedge clk) + if(we & !wp[0]) din_tmp1 <= #1 din[19:4]; + +always @(mode or din_tmp1 or din) + case(mode) // synopsys parallel_case full_case + 2'h0: din_tmp = {din[19:4], din_tmp1}; // 16 Bit Output + 2'h1: din_tmp = {14'h0, din[19:2]}; // 18 bit Output + 2'h2: din_tmp = {11'h0, din[19:0]}; // 20 Bit Output + endcase + +always @(posedge clk) + if(we & (!m16b | (m16b & wp[0]) ) ) mem[ wp[2:1] ] <= #1 din_tmp; + +endmodule + +`endif + +`ifdef AC97_IN_FIFO_DEPTH_8 + +// 8 entry deep verion of the input FIFO + +module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [19:0] din; +input we; +output [31:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:7]; +reg [31:0] dout; + +reg [4:0] wp; +reg [3:0] rp; + +wire [4:0] wp_p1; + +reg [1:0] status; +reg [15:0] din_tmp1; +reg [31:0] din_tmp; +wire m16b; +reg full, empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 5'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = m16b ? (wp + 5'h1) : (wp + 5'h2); + +always @(posedge clk) + if(!en) rp <= #1 4'h0; + else + if(re) rp <= #1 rp + 4'h1; + +always @(posedge clk) + status <= #1 ((rp[2:1] - wp[3:2]) - 2'h1); + +always @(posedge clk) + empty <= #1 (wp[4:1] == rp[3:0]) & (m16b ? !wp[0] : 1'b0); + +always @(posedge clk) + full <= #1 (wp[3:1] == rp[2:0]) & (wp[4] != rp[3]); + +// Fifo Output +always @(posedge clk) + dout <= #1 mem[ rp[2:0] ]; + +// Fifo Input Half Word Latch +always @(posedge clk) + if(we & !wp[0]) din_tmp1 <= #1 din[19:4]; + +always @(mode or din_tmp1 or din) + case(mode) // synopsys parallel_case full_case + 2'h0: din_tmp = {din[19:4], din_tmp1}; // 16 Bit Output + 2'h1: din_tmp = {14'h0, din[19:2]}; // 18 bit Output + 2'h2: din_tmp = {11'h0, din[19:0]}; // 20 Bit Output + endcase + +always @(posedge clk) + if(we & (!m16b | (m16b & wp[0]) ) ) mem[ wp[3:1] ] <= #1 din_tmp; + +endmodule + +`endif + + +`ifdef AC97_IN_FIFO_DEPTH_16 + +// 16 entry deep verion of the input FIFO + +module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [19:0] din; +input we; +output [31:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:15]; +reg [31:0] dout; + +reg [5:0] wp; +reg [4:0] rp; + +wire [5:0] wp_p1; + +reg [1:0] status; +reg [15:0] din_tmp1; +reg [31:0] din_tmp; +wire m16b; +reg full, empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 6'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = m16b ? (wp + 6'h1) : (wp + 6'h2); + +always @(posedge clk) + if(!en) rp <= #1 5'h0; + else + if(re) rp <= #1 rp + 5'h1; + +always @(posedge clk) + status <= #1 ((rp[3:2] - wp[4:3]) - 2'h1); + +always @(posedge clk) + empty <= #1 (wp[5:1] == rp[4:0]) & (m16b ? !wp[0] : 1'b0); + +always @(posedge clk) + full <= #1 (wp[4:1] == rp[3:0]) & (wp[5] != rp[4]); + +// Fifo Output +always @(posedge clk) + dout <= #1 mem[ rp[3:0] ]; + +// Fifo Input Half Word Latch +always @(posedge clk) + if(we & !wp[0]) din_tmp1 <= #1 din[19:4]; + +always @(mode or din_tmp1 or din) + case(mode) // synopsys parallel_case full_case + 2'h0: din_tmp = {din[19:4], din_tmp1}; // 16 Bit Output + 2'h1: din_tmp = {14'h0, din[19:2]}; // 18 bit Output + 2'h2: din_tmp = {11'h0, din[19:0]}; // 20 Bit Output + endcase + +always @(posedge clk) + if(we & (!m16b | (m16b & wp[0]) ) ) mem[ wp[4:1] ] <= #1 din_tmp; + +endmodule + +`endif diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v new file mode 100644 index 000000000..082f9dacc --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v @@ -0,0 +1,126 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Interrupt Logic //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_int.v,v 1.3 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_int.v,v $ +// Revision 1.3 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:18 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_int(clk, rst, + + // Register File Interface + int_set, + + // FIFO Interface + cfg, status, full_empty, full, empty, re, we + ); + +input clk, rst; +output [2:0] int_set; + +input [7:0] cfg; +input [1:0] status; +input full_empty, full, empty, re, we; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [2:0] int_set; + +//////////////////////////////////////////////////////////////////// +// +// Interrupt Logic +// + +always @(posedge clk or negedge rst) + if(!rst) int_set[0] <= #1 1'b0; + else + case(cfg[5:4]) // synopsys parallel_case full_case + // 1/4 full/empty + 2'h2: int_set[0] <= #1 cfg[0] & (full_empty | (status == 2'h0)); + // 1/2 full/empty + 2'h1: int_set[0] <= #1 cfg[0] & (full_empty | (status[1] == 1'h0)); + // 3/4 full/empty + 2'h0: int_set[0] <= #1 cfg[0] & (full_empty | (status < 2'h3)); + 2'h3: int_set[0] <= #1 cfg[0] & full_empty; + endcase + +always @(posedge clk or negedge rst) + if(!rst) int_set[1] <= #1 1'b0; + else + if(empty & re) int_set[1] <= #1 1'b1; + +always @(posedge clk or negedge rst) + if(!rst) int_set[2] <= #1 1'b0; + else + if(full & we) int_set[2] <= #1 1'b1; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v new file mode 100644 index 000000000..a2fb29e6d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v @@ -0,0 +1,348 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Output FIFO //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_out_fifo.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_out_fifo.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/11 03:21:22 rudi +// +// - Added defines to select fifo depth between 4, 8 and 16 entries. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:16 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +`ifdef AC97_OUT_FIFO_DEPTH_4 + +// 4 Entry Deep version of the Output FIFO + +module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [31:0] din; +input we; +output [19:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:3]; + +reg [2:0] wp; +reg [3:0] rp; + +wire [2:0] wp_p1; + +reg [1:0] status; +reg [19:0] dout; +wire [31:0] dout_tmp; +wire [15:0] dout_tmp1; +wire m16b; +reg empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 3'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = wp + 3'h1; + +always @(posedge clk) + if(!en) rp <= #1 4'h0; + else + if(re & m16b) rp <= #1 rp + 4'h1; + else + if(re & !m16b) rp <= #1 rp + 4'h2; + +always @(posedge clk) + status <= #1 (wp[1:0] - rp[2:1]) - 2'h1; + +wire [3:0] rp_p1 = rp[3:0] + 4'h1; + +always @(posedge clk) + empty <= #1 (rp_p1[3:1] == wp[2:0]) & (m16b ? rp_p1[0] : 1'b1); + +assign full = (wp[1:0] == rp[2:1]) & (wp[2] != rp[3]); + +// Fifo Output +assign dout_tmp = mem[ rp[2:1] ]; + +// Fifo Output Half Word Select +assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0]; + +always @(posedge clk) + if(!en) dout <= #1 20'h0; + else + if(re) + case(mode) // synopsys parallel_case full_case + 2'h0: dout <= #1 {dout_tmp1, 4'h0}; // 16 Bit Output + 2'h1: dout <= #1 {dout_tmp[17:0], 2'h0}; // 18 bit Output + 2'h2: dout <= #1 dout_tmp[19:0]; // 20 Bit Output + endcase + +always @(posedge clk) + if(we) mem[wp[1:0]] <= #1 din; + +endmodule + +`endif + +`ifdef AC97_OUT_FIFO_DEPTH_8 + +// 8 Entry Deep version of the Output FIFO + +module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [31:0] din; +input we; +output [19:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:7]; + +reg [3:0] wp; +reg [4:0] rp; + +wire [3:0] wp_p1; + +reg [1:0] status; +reg [19:0] dout; +wire [31:0] dout_tmp; +wire [15:0] dout_tmp1; +wire m16b; +reg empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 4'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = wp + 4'h1; + +always @(posedge clk) + if(!en) rp <= #1 5'h0; + else + if(re & m16b) rp <= #1 rp + 5'h1; + else + if(re & !m16b) rp <= #1 rp + 5'h2; + +always @(posedge clk) + status <= #1 (wp[2:1] - rp[3:2]) - 2'h1; + +wire [4:0] rp_p1 = rp[4:0] + 5'h1; + +always @(posedge clk) + empty <= #1 (rp_p1[4:1] == wp[3:0]) & (m16b ? rp_p1[0] : 1'b1); + +assign full = (wp[2:0] == rp[3:1]) & (wp[3] != rp[4]); + +// Fifo Output +assign dout_tmp = mem[ rp[3:1] ]; + +// Fifo Output Half Word Select +assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0]; + +always @(posedge clk) + if(!en) dout <= #1 20'h0; + else + if(re) + case(mode) // synopsys parallel_case full_case + 2'h0: dout <= #1 {dout_tmp1, 4'h0}; // 16 Bit Output + 2'h1: dout <= #1 {dout_tmp[17:0], 2'h0}; // 18 bit Output + 2'h2: dout <= #1 dout_tmp[19:0]; // 20 Bit Output + endcase + + +always @(posedge clk) + if(we) mem[wp[2:0]] <= #1 din; + +endmodule + +`endif + + +`ifdef AC97_OUT_FIFO_DEPTH_16 + +// 16 Entry Deep version of the Output FIFO + +module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty); + +input clk, rst; +input en; +input [1:0] mode; +input [31:0] din; +input we; +output [19:0] dout; +input re; +output [1:0] status; +output full; +output empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] mem[0:15]; + +reg [4:0] wp; +reg [5:0] rp; + +wire [4:0] wp_p1; + +reg [1:0] status; +reg [19:0] dout; +wire [31:0] dout_tmp; +wire [15:0] dout_tmp1; +wire m16b; +reg empty; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign m16b = (mode == 2'h0); // 16 Bit Mode + +always @(posedge clk) + if(!en) wp <= #1 5'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = wp + 4'h1; + +always @(posedge clk) + if(!en) rp <= #1 6'h0; + else + if(re & m16b) rp <= #1 rp + 6'h1; + else + if(re & !m16b) rp <= #1 rp + 6'h2; + +always @(posedge clk) + status <= #1 (wp[3:2] - rp[4:3]) - 2'h1; + +wire [5:0] rp_p1 = rp[5:0] + 6'h1; + +always @(posedge clk) + empty <= #1 (rp_p1[5:1] == wp[4:0]) & (m16b ? rp_p1[0] : 1'b1); + +assign full = (wp[3:0] == rp[4:1]) & (wp[4] != rp[5]); + +// Fifo Output +assign dout_tmp = mem[ rp[4:1] ]; + +// Fifo Output Half Word Select +assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0]; + +always @(posedge clk) + if(!en) dout <= #1 20'h0; + else + if(re) + case(mode) // synopsys parallel_case full_case + 2'h0: dout <= #1 {dout_tmp1, 4'h0}; // 16 Bit Output + 2'h1: dout <= #1 {dout_tmp[17:0], 2'h0}; // 18 bit Output + 2'h2: dout <= #1 dout_tmp[19:0]; // 20 Bit Output + endcase + + +always @(posedge clk) + if(we) mem[wp[3:0]] <= #1 din; + +endmodule + +`endif diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v new file mode 100644 index 000000000..f7881f28b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v @@ -0,0 +1,336 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// PCM Request Controller //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_prc.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_prc.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:17 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_prc(clk, rst, + + // SR Slot Interface + valid, in_valid, out_slt0, + in_slt0, in_slt1, + + // Codec Register Access + crac_valid, crac_wr, + + // Channel Configuration + oc0_cfg, oc1_cfg, oc2_cfg, oc3_cfg, oc4_cfg, oc5_cfg, + ic0_cfg, ic1_cfg, ic2_cfg, + + // FIFO Status + o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, + o9_empty, i3_full, i4_full, i6_full, + + // FIFO Control + o3_re, o4_re, o6_re, o7_re, o8_re, o9_re, + i3_we, i4_we, i6_we + + ); +input clk, rst; + +input valid; +input [2:0] in_valid; +output [15:0] out_slt0; +input [15:0] in_slt0; +input [19:0] in_slt1; + +input crac_valid; +input crac_wr; + +input [7:0] oc0_cfg; +input [7:0] oc1_cfg; +input [7:0] oc2_cfg; +input [7:0] oc3_cfg; +input [7:0] oc4_cfg; +input [7:0] oc5_cfg; + +input [7:0] ic0_cfg; +input [7:0] ic1_cfg; +input [7:0] ic2_cfg; + +input o3_empty; +input o4_empty; +input o6_empty; +input o7_empty; +input o8_empty; +input o9_empty; +input i3_full; +input i4_full; +input i6_full; + +output o3_re; +output o4_re; +output o6_re; +output o7_re; +output o8_re; +output o9_re; +output i3_we; +output i4_we; +output i6_we; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire o3_re_l; +wire o4_re_l; +wire o6_re_l; +wire o7_re_l; +wire o8_re_l; +wire o9_re_l; + +reg crac_valid_r; +reg crac_wr_r; + +//////////////////////////////////////////////////////////////////// +// +// Output Tag Assembly +// + +assign out_slt0[15] = |out_slt0[14:6]; + +assign out_slt0[14] = crac_valid_r; +assign out_slt0[13] = crac_wr_r; + +assign out_slt0[12] = o3_re_l; +assign out_slt0[11] = o4_re_l; +assign out_slt0[10] = 1'b0; +assign out_slt0[09] = o6_re_l; +assign out_slt0[08] = o7_re_l; +assign out_slt0[07] = o8_re_l; +assign out_slt0[06] = o9_re_l; +assign out_slt0[5:0] = 6'h0; + +//////////////////////////////////////////////////////////////////// +// +// FIFO Control +// + +always @(posedge clk) + if(valid) crac_valid_r <= #1 crac_valid; + +always @(posedge clk) + if(valid) crac_wr_r <= #1 crac_valid & crac_wr; + +// Output Channel 0 (Out Slot 3) +ac97_fifo_ctrl u0( + .clk( clk ), + .valid( valid ), + .ch_en( oc0_cfg[0] ), + .srs( oc0_cfg[1] ), + .full_empty( o3_empty ), + .req( ~in_slt1[11] ), + .crdy( in_slt0[15] ), + .en_out( o3_re ), + .en_out_l( o3_re_l ) + ); + +// Output Channel 1 (Out Slot 4) +ac97_fifo_ctrl u1( + .clk( clk ), + .valid( valid ), + .ch_en( oc1_cfg[0] ), + .srs( oc1_cfg[1] ), + .full_empty( o4_empty ), + .req( ~in_slt1[10] ), + .crdy( in_slt0[15] ), + .en_out( o4_re ), + .en_out_l( o4_re_l ) + ); + +`ifdef AC97_CENTER +// Output Channel 2 (Out Slot 6) +ac97_fifo_ctrl u2( + .clk( clk ), + .valid( valid ), + .ch_en( oc2_cfg[0] ), + .srs( oc2_cfg[1] ), + .full_empty( o6_empty ), + .req( ~in_slt1[8] ), + .crdy( in_slt0[15] ), + .en_out( o6_re ), + .en_out_l( o6_re_l ) + ); +`else +assign o6_re = 1'b0; +assign o6_re_l = 1'b0; +`endif + +`ifdef AC97_SURROUND +// Output Channel 3 (Out Slot 7) +ac97_fifo_ctrl u3( + .clk( clk ), + .valid( valid ), + .ch_en( oc3_cfg[0] ), + .srs( oc3_cfg[1] ), + .full_empty( o7_empty ), + .req( ~in_slt1[7] ), + .crdy( in_slt0[15] ), + .en_out( o7_re ), + .en_out_l( o7_re_l ) + ); + +// Output Channel 4 (Out Slot 8) +ac97_fifo_ctrl u4( + .clk( clk ), + .valid( valid ), + .ch_en( oc4_cfg[0] ), + .srs( oc4_cfg[1] ), + .full_empty( o8_empty ), + .req( ~in_slt1[6] ), + .crdy( in_slt0[15] ), + .en_out( o8_re ), + .en_out_l( o8_re_l ) + ); +`else +assign o7_re = 1'b0; +assign o7_re_l = 1'b0; +assign o8_re = 1'b0; +assign o8_re_l = 1'b0; +`endif + +`ifdef AC97_LFE +// Output Channel 5 (Out Slot 9) +ac97_fifo_ctrl u5( + .clk( clk ), + .valid( valid ), + .ch_en( oc5_cfg[0] ), + .srs( oc5_cfg[1] ), + .full_empty( o9_empty ), + .req( ~in_slt1[5] ), + .crdy( in_slt0[15] ), + .en_out( o9_re ), + .en_out_l( o9_re_l ) + ); +`else +assign o9_re = 1'b0; +assign o9_re_l = 1'b0; +`endif + +`ifdef AC97_SIN +// Input Channel 0 (In Slot 3) +ac97_fifo_ctrl u6( + .clk( clk ), + .valid( in_valid[0] ), + .ch_en( ic0_cfg[0] ), + .srs( ic0_cfg[1] ), + .full_empty( i3_full ), + .req( in_slt0[12] ), + .crdy( in_slt0[15] ), + .en_out( i3_we ), + .en_out_l( ) + ); + +// Input Channel 1 (In Slot 4) +ac97_fifo_ctrl u7( + .clk( clk ), + .valid( in_valid[1] ), + .ch_en( ic1_cfg[0] ), + .srs( ic1_cfg[1] ), + .full_empty( i4_full ), + .req( in_slt0[11] ), + .crdy( in_slt0[15] ), + .en_out( i4_we ), + .en_out_l( ) + ); +`else +assign i3_we = 1'b0; +assign i4_we = 1'b0; +`endif + +`ifdef AC97_MICIN +// Input Channel 2 (In Slot 6) +ac97_fifo_ctrl u8( + .clk( clk ), + .valid( in_valid[2] ), + .ch_en( ic2_cfg[0] ), + .srs( ic2_cfg[1] ), + .full_empty( i6_full ), + .req( in_slt0[9] ), + .crdy( in_slt0[15] ), + .en_out( i6_we ), + .en_out_l( ) + ); +`else +assign i6_we = 1'b0; +`endif + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v new file mode 100644 index 000000000..57839b982 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v @@ -0,0 +1,306 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_rf.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_rf.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:17 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_rf(clk, rst, + + adr, rf_dout, rf_din, + rf_we, rf_re, int, ac97_rst_force, + resume_req, suspended, + + crac_we, crac_din, crac_out, + crac_rd_done, crac_wr_done, + + oc0_cfg, oc1_cfg, oc2_cfg, oc3_cfg, oc4_cfg, oc5_cfg, + ic0_cfg, ic1_cfg, ic2_cfg, + oc0_int_set, oc1_int_set, oc2_int_set, oc3_int_set, + oc4_int_set, oc5_int_set, + ic0_int_set, ic1_int_set, ic2_int_set + + ); + +input clk,rst; + +input [3:0] adr; +output [31:0] rf_dout; +input [31:0] rf_din; +input rf_we; +input rf_re; +output int; +output ac97_rst_force; +output resume_req; +input suspended; + +output crac_we; +input [15:0] crac_din; +output [31:0] crac_out; +input crac_rd_done, crac_wr_done; + +output [7:0] oc0_cfg; +output [7:0] oc1_cfg; +output [7:0] oc2_cfg; +output [7:0] oc3_cfg; +output [7:0] oc4_cfg; +output [7:0] oc5_cfg; + +output [7:0] ic0_cfg; +output [7:0] ic1_cfg; +output [7:0] ic2_cfg; + +input [2:0] oc0_int_set; +input [2:0] oc1_int_set; +input [2:0] oc2_int_set; +input [2:0] oc3_int_set; +input [2:0] oc4_int_set; +input [2:0] oc5_int_set; +input [2:0] ic0_int_set; +input [2:0] ic1_int_set; +input [2:0] ic2_int_set; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] rf_dout; + +reg [31:0] csr_r; +reg [31:0] occ0_r; +reg [15:0] occ1_r; +reg [23:0] icc_r; +reg [31:0] crac_r; +reg [28:0] intm_r; +reg [28:0] ints_r; +reg int; +wire [28:0] int_all; +wire [31:0] csr, occ0, occ1, icc, crac, intm, ints; +reg [15:0] crac_dout_r; +reg ac97_rst_force; +reg resume_req; + +// Aliases +assign csr = {30'h0, suspended, 1'h0}; +assign occ0 = occ0_r; +assign occ1 = {16'h0, occ1_r}; +assign icc = {8'h0, icc_r}; +assign crac = {crac_r[7], 8'h0, crac_r[6:0], crac_din}; +assign intm = {3'h0, intm_r}; +assign ints = {3'h0, ints_r}; + +assign crac_out = {crac_r[7], 8'h0, crac_r[6:0], crac_dout_r}; + +//////////////////////////////////////////////////////////////////// +// +// Register WISHBONE Interface +// + +always @(adr or csr or occ0 or occ1 or icc or crac or intm or ints) + case(adr[2:0]) // synopsys parallel_case full_case + 0: rf_dout = csr; + 1: rf_dout = occ0; + 2: rf_dout = occ1; + 3: rf_dout = icc; + 4: rf_dout = crac; + 5: rf_dout = intm; + 6: rf_dout = ints; + endcase + +always @(posedge clk or negedge rst) + if(!rst) csr_r <= #1 1'b0; + else + if(rf_we & (adr[2:0]==3'h0)) csr_r <= #1 rf_din; + +always @(posedge clk) + if(rf_we & (adr[2:0]==3'h0)) ac97_rst_force <= #1 rf_din[0]; + else ac97_rst_force <= #1 1'b0; + +always @(posedge clk) + if(rf_we & (adr[2:0]==3'h0)) resume_req <= #1 rf_din[1]; + else resume_req <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) occ0_r <= #1 1'b0; + else + if(rf_we & (adr[2:0]==3'h1)) occ0_r <= #1 rf_din; + +always @(posedge clk or negedge rst) + if(!rst) occ1_r <= #1 1'b0; + else + if(rf_we & (adr[2:0]==3'h2)) occ1_r <= #1 rf_din[23:0]; + +always @(posedge clk or negedge rst) + if(!rst) icc_r <= #1 1'b0; + else + if(rf_we & (adr[2:0]==3'h3)) icc_r <= #1 rf_din[23:0]; + +assign crac_we = rf_we & (adr[2:0]==3'h4); + +always @(posedge clk or negedge rst) + if(!rst) crac_r <= #1 1'b0; + else + if(crac_we) crac_r <= #1 {rf_din[31], rf_din[22:16]}; + +always @(posedge clk) + if(crac_we) crac_dout_r <= #1 rf_din[15:0]; + +always @(posedge clk or negedge rst) + if(!rst) intm_r <= #1 1'b0; + else + if(rf_we & (adr[2:0]==3'h5)) intm_r <= #1 rf_din[28:0]; + +// Interrupt Source Register +always @(posedge clk or negedge rst) + if(!rst) ints_r <= #1 1'b0; + else + if(rf_re & (adr[2:0]==3'h6)) ints_r <= #1 1'b0; + else + begin + if(crac_rd_done) ints_r[0] <= #1 1'b1; + if(crac_wr_done) ints_r[1] <= #1 1'b1; + if(oc0_int_set[0]) ints_r[2] <= #1 1'b1; + if(oc0_int_set[1]) ints_r[3] <= #1 1'b1; + if(oc0_int_set[2]) ints_r[4] <= #1 1'b1; + if(oc1_int_set[0]) ints_r[5] <= #1 1'b1; + if(oc1_int_set[1]) ints_r[6] <= #1 1'b1; + if(oc1_int_set[2]) ints_r[7] <= #1 1'b1; +`ifdef AC97_CENTER + if(oc2_int_set[0]) ints_r[8] <= #1 1'b1; + if(oc2_int_set[1]) ints_r[9] <= #1 1'b1; + if(oc2_int_set[2]) ints_r[10] <= #1 1'b1; +`endif + +`ifdef AC97_SURROUND + if(oc3_int_set[0]) ints_r[11] <= #1 1'b1; + if(oc3_int_set[1]) ints_r[12] <= #1 1'b1; + if(oc3_int_set[2]) ints_r[13] <= #1 1'b1; + if(oc4_int_set[0]) ints_r[14] <= #1 1'b1; + if(oc4_int_set[1]) ints_r[15] <= #1 1'b1; + if(oc4_int_set[2]) ints_r[16] <= #1 1'b1; +`endif + +`ifdef AC97_LFE + if(oc5_int_set[0]) ints_r[17] <= #1 1'b1; + if(oc5_int_set[1]) ints_r[18] <= #1 1'b1; + if(oc5_int_set[2]) ints_r[19] <= #1 1'b1; +`endif + +`ifdef AC97_SIN + if(ic0_int_set[0]) ints_r[20] <= #1 1'b1; + if(ic0_int_set[1]) ints_r[21] <= #1 1'b1; + if(ic0_int_set[2]) ints_r[22] <= #1 1'b1; + if(ic1_int_set[0]) ints_r[23] <= #1 1'b1; + if(ic1_int_set[1]) ints_r[24] <= #1 1'b1; + if(ic1_int_set[2]) ints_r[25] <= #1 1'b1; +`endif + +`ifdef AC97_MICIN + if(ic2_int_set[0]) ints_r[26] <= #1 1'b1; + if(ic2_int_set[1]) ints_r[27] <= #1 1'b1; + if(ic2_int_set[2]) ints_r[28] <= #1 1'b1; +`endif + end + +//////////////////////////////////////////////////////////////////// +// +// Register Internal Interface +// + +assign oc0_cfg = occ0[7:0]; +assign oc1_cfg = occ0[15:8]; +assign oc2_cfg = occ0[23:16]; +assign oc3_cfg = occ0[31:24]; +assign oc4_cfg = occ1[7:0]; +assign oc5_cfg = occ1[15:8]; + +assign ic0_cfg = icc[7:0]; +assign ic1_cfg = icc[15:8]; +assign ic2_cfg = icc[23:16]; + +//////////////////////////////////////////////////////////////////// +// +// Interrupt Generation +// + +assign int_all = intm_r & ints_r; + +always @(posedge clk) + int <= #1 |int_all; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v new file mode 100644 index 000000000..8b16bcfa4 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v @@ -0,0 +1,103 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller Reset Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_rst.v,v 1.1 2001/08/03 06:54:50 rudi Exp $ +// +// $Date: 2001/08/03 06:54:50 $ +// $Revision: 1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_rst.v,v $ +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:19 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_rst(clk, rst, rst_force, ps_ce, ac97_rst_); +input clk, rst; +input rst_force; +output ps_ce; +output ac97_rst_; + +reg ac97_rst_; +reg [2:0] cnt; +wire ce; +wire to; +reg [5:0] ps_cnt; +wire ps_ce; + +always @(posedge clk or negedge rst) + if(!rst) ac97_rst_ <= #1 0; + else + if(rst_force) ac97_rst_ <= #1 0; + else + if(to) ac97_rst_ <= #1 1; + +assign to = (cnt == `AC97_RST_DEL); + +always @(posedge clk or negedge rst) + if(!rst) cnt <= #1 0; + else + if(rst_force) cnt <= #1 0; + else + if(ce) cnt <= #1 cnt + 1; + +assign ce = ps_ce & (cnt != `AC97_RST_DEL); + +always @(posedge clk or negedge rst) + if(!rst) ps_cnt <= #1 0; + else + if(ps_ce | rst_force) ps_cnt <= #1 0; + else ps_cnt <= #1 ps_cnt + 1; + +assign ps_ce = (ps_cnt == `AC97_250_PS); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v new file mode 100644 index 000000000..9a8d8b405 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Serial Input Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_sin.v,v 1.2 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_sin.v,v $ +// Revision 1.2 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:15 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_sin(clk, rst, + + out_le, slt0, slt1, slt2, slt3, slt4, + slt6, + + sdata_in + ); + +input clk, rst; + +// -------------------------------------- +// Misc Signals +input [5:0] out_le; +output [15:0] slt0; +output [19:0] slt1; +output [19:0] slt2; +output [19:0] slt3; +output [19:0] slt4; +output [19:0] slt6; + +// -------------------------------------- +// AC97 Codec Interface +input sdata_in; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg sdata_in_r; +reg [19:0] sr; + +reg [15:0] slt0; +reg [19:0] slt1; +reg [19:0] slt2; +reg [19:0] slt3; +reg [19:0] slt4; +reg [19:0] slt6; + +//////////////////////////////////////////////////////////////////// +// +// Output Registers +// + +always @(posedge clk) + if(out_le[0]) slt0 <= #1 sr[15:0]; + +always @(posedge clk) + if(out_le[1]) slt1 <= #1 sr; + +always @(posedge clk) + if(out_le[2]) slt2 <= #1 sr; + +always @(posedge clk) + if(out_le[3]) slt3 <= #1 sr; + +always @(posedge clk) + if(out_le[4]) slt4 <= #1 sr; + +always @(posedge clk) + if(out_le[5]) slt6 <= #1 sr; + +//////////////////////////////////////////////////////////////////// +// +// Serial Shift Register +// + +always @(negedge clk) + sdata_in_r <= #1 sdata_in; + +always @(posedge clk) + sr <= #1 {sr[18:0], sdata_in_r }; + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v new file mode 100644 index 000000000..2236d1e1c --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v @@ -0,0 +1,205 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Serial Output Controller //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_soc.v,v 1.3 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_soc.v,v $ +// Revision 1.3 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.2 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:15 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_soc(clk, wclk, rst, + ps_ce, resume, suspended, + sync, out_le, in_valid, ld, valid + ); + +input clk, wclk, rst; +input ps_ce; +input resume; +output suspended; +output sync; +output [5:0] out_le; +output [2:0] in_valid; +output ld; +output valid; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [7:0] cnt; +reg sync_beat; +reg sync_resume; +reg [5:0] out_le; +reg ld; +reg valid; +reg [2:0] in_valid; +reg bit_clk_r; +reg bit_clk_r1; +reg bit_clk_e; +reg suspended; +wire to; +reg [5:0] to_cnt; +reg [3:0] res_cnt; +wire resume_done; + +assign sync = sync_beat | sync_resume; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk or negedge rst) + if(!rst) cnt <= #1 8'hff; + else + if(suspended) cnt <= #1 8'hff; + else cnt <= #1 cnt + 8'h1; + +always @(posedge clk) + ld <= #1 (cnt == 8'h00); + +always @(posedge clk) + sync_beat <= #1 (cnt == 8'h00) | ((cnt > 8'h00) & (cnt < 8'h10)); + +always @(posedge clk) + valid <= #1 (cnt > 8'h39); + +always @(posedge clk) + out_le[0] <= #1 (cnt == 8'h11); // Slot 0 Latch Enable + +always @(posedge clk) + out_le[1] <= #1 (cnt == 8'h25); // Slot 1 Latch Enable + +always @(posedge clk) + out_le[2] <= #1 (cnt == 8'h39); // Slot 2 Latch Enable + +always @(posedge clk) + out_le[3] <= #1 (cnt == 8'h4d); // Slot 3 Latch Enable + +always @(posedge clk) + out_le[4] <= #1 (cnt == 8'h61); // Slot 4 Latch Enable + +always @(posedge clk) + out_le[5] <= #1 (cnt == 8'h89); // Slot 6 Latch Enable + +always @(posedge clk) + in_valid[0] <= #1 (cnt > 8'h4d); // Input Slot 3 Valid + +always @(posedge clk) + in_valid[1] <= #1 (cnt > 8'h61); // Input Slot 3 Valid + +always @(posedge clk) + in_valid[2] <= #1 (cnt > 8'h89); // Input Slot 3 Valid + +//////////////////////////////////////////////////////////////////// +// +// Suspend Detect +// + +always @(posedge wclk) + bit_clk_r <= #1 clk; + +always @(posedge wclk) + bit_clk_r1 <= #1 bit_clk_r; + +always @(posedge wclk) + bit_clk_e <= #1 (bit_clk_r & !bit_clk_r1) | (!bit_clk_r & bit_clk_r1); + +always @(posedge wclk) + suspended <= #1 to; + +assign to = (to_cnt == `AC97_SUSP_DET); + +always @(posedge wclk or negedge rst) + if(!rst) to_cnt <= #1 6'h0; + else + if(bit_clk_e) to_cnt <= #1 6'h0; + else + if(!to) to_cnt <= #1 to_cnt + 6'h1; + +//////////////////////////////////////////////////////////////////// +// +// Resume Signaling +// + +always @(posedge wclk or negedge rst) + if(!rst) sync_resume <= #1 1'b0; + else + if(resume_done) sync_resume <= #1 1'b0; + else + if(suspended & resume) sync_resume <= #1 1'b1; + +assign resume_done = (res_cnt == `AC97_RES_SIG); + +always @(posedge wclk) + if(!sync_resume) res_cnt <= #1 4'h0; + else + if(ps_ce) res_cnt <= #1 res_cnt + 4'h1; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v new file mode 100644 index 000000000..7d9d34b73 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v @@ -0,0 +1,183 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// Serial Output Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_sout.v,v 1.2 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_sout.v,v $ +// Revision 1.2 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:15 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_sout(clk, rst, + + so_ld, slt0, slt1, slt2, slt3, slt4, + slt6, slt7, slt8, slt9, + + sdata_out + ); + +input clk, rst; + +// -------------------------------------- +// Misc Signals +input so_ld; +input [15:0] slt0; +input [19:0] slt1; +input [19:0] slt2; +input [19:0] slt3; +input [19:0] slt4; +input [19:0] slt6; +input [19:0] slt7; +input [19:0] slt8; +input [19:0] slt9; + +// -------------------------------------- +// AC97 Codec Interface +output sdata_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire sdata_out; + +reg [15:0] slt0_r; +reg [19:0] slt1_r; +reg [19:0] slt2_r; +reg [19:0] slt3_r; +reg [19:0] slt4_r; +reg [19:0] slt5_r; +reg [19:0] slt6_r; +reg [19:0] slt7_r; +reg [19:0] slt8_r; +reg [19:0] slt9_r; +reg [19:0] slt10_r; +reg [19:0] slt11_r; +reg [19:0] slt12_r; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +//////////////////////////////////////////////////////////////////// +// +// Serial Shift Register +// + +assign sdata_out = slt0_r[15]; + +always @(posedge clk) + if(so_ld) slt0_r <= #1 slt0; + else slt0_r <= #1 {slt0_r[14:0], slt1_r[19]}; + +always @(posedge clk) + if(so_ld) slt1_r <= #1 slt1; + else slt1_r <= #1 {slt1_r[18:0], slt2_r[19]}; + +always @(posedge clk) + if(so_ld) slt2_r <= #1 slt2; + else slt2_r <= #1 {slt2_r[18:0], slt3_r[19]}; + +always @(posedge clk) + if(so_ld) slt3_r <= #1 slt3; + else slt3_r <= #1 {slt3_r[18:0], slt4_r[19]}; + +always @(posedge clk) + if(so_ld) slt4_r <= #1 slt4; + else slt4_r <= #1 {slt4_r[18:0], slt5_r[19]}; + +always @(posedge clk) + if(so_ld) slt5_r <= #1 20'h0; + else slt5_r <= #1 {slt5_r[18:0], slt6_r[19]}; + +always @(posedge clk) + if(so_ld) slt6_r <= #1 slt6; + else slt6_r <= #1 {slt6_r[18:0], slt7_r[19]}; + +always @(posedge clk) + if(so_ld) slt7_r <= #1 slt7; + else slt7_r <= #1 {slt7_r[18:0], slt8_r[19]}; + +always @(posedge clk) + if(so_ld) slt8_r <= #1 slt8; + else slt8_r <= #1 {slt8_r[18:0], slt9_r[19]}; + +always @(posedge clk) + if(so_ld) slt9_r <= #1 slt9; + else slt9_r <= #1 {slt9_r[18:0], slt10_r[19]}; + +always @(posedge clk) + if(so_ld) slt10_r <= #1 20'h0; + else slt10_r <= #1 {slt10_r[18:0], slt11_r[19]}; + +always @(posedge clk) + if(so_ld) slt11_r <= #1 20'h0; + else slt11_r <= #1 {slt11_r[18:0], slt12_r[19]}; + +always @(posedge clk) + if(so_ld) slt12_r <= #1 20'h0; + else slt12_r <= #1 {slt12_r[18:0], 1'b0 }; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v new file mode 100644 index 000000000..3460d4a45 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v @@ -0,0 +1,761 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_top.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_top.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:14 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_top(clk_i, rst_i, + + wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, + + int_o, dma_req_o, dma_ack_i, + suspended_o, + + bit_clk_pad_i, sync_pad_o, sdata_pad_o, sdata_pad_i, + ac97_reset_pad_o_ + ); + +input clk_i, rst_i; + +// -------------------------------------- +// WISHBONE SLAVE INTERFACE +input [31:0] wb_data_i; +output [31:0] wb_data_o; +input [31:0] wb_addr_i; +input [3:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; + +// -------------------------------------- +// Misc Signals +output int_o; +output [8:0] dma_req_o; +input [8:0] dma_ack_i; + +// -------------------------------------- +// Suspend Resume Interface +output suspended_o; + +// -------------------------------------- +// AC97 Codec Interface +input bit_clk_pad_i; +output sync_pad_o; +output sdata_pad_o; +input sdata_pad_i; +output ac97_reset_pad_o_; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +// Serial Output register interface +wire [15:0] out_slt0; +wire [19:0] out_slt1; +wire [19:0] out_slt2; +wire [19:0] out_slt3; +wire [19:0] out_slt4; +wire [19:0] out_slt6; +wire [19:0] out_slt7; +wire [19:0] out_slt8; +wire [19:0] out_slt9; + +// Serial Input register interface +wire [15:0] in_slt0; +wire [19:0] in_slt1; +wire [19:0] in_slt2; +wire [19:0] in_slt3; +wire [19:0] in_slt4; +wire [19:0] in_slt6; + +// Serial IO Controller Interface +wire ld; +wire valid; +wire [5:0] out_le; +wire [2:0] in_valid; +wire ps_ce; + +// Valid Sync +reg valid_s1, valid_s; +reg [2:0] in_valid_s1, in_valid_s; + +// Out FIFO interface +wire [31:0] wb_din; +wire [1:0] o3_mode, o4_mode, o6_mode, o7_mode, o8_mode, o9_mode; +wire o3_re, o4_re, o6_re, o7_re, o8_re, o9_re; +wire o3_we, o4_we, o6_we, o7_we, o8_we, o9_we; +wire [1:0] o3_status, o4_status, o6_status, o7_status, o8_status, o9_status; +wire o3_full, o4_full, o6_full, o7_full, o8_full, o9_full; +wire o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, o9_empty; + +// In FIFO interface +wire [31:0] i3_dout, i4_dout, i6_dout; +wire [1:0] i3_mode, i4_mode, i6_mode; +wire i3_we, i4_we, i6_we; +wire i3_re, i4_re, i6_re; +wire [1:0] i3_status, i4_status, i6_status; +wire i3_full, i4_full, i6_full; +wire i3_empty, i4_empty, i6_empty; + +// Register File Interface +wire [3:0] adr; +wire [31:0] rf_dout; +wire [31:0] rf_din; +wire rf_we; +wire rf_re; +wire ac97_rst_force; +wire resume_req; +wire crac_we; +wire [15:0] crac_din; +wire [31:0] crac_out; +wire [7:0] oc0_cfg; +wire [7:0] oc1_cfg; +wire [7:0] oc2_cfg; +wire [7:0] oc3_cfg; +wire [7:0] oc4_cfg; +wire [7:0] oc5_cfg; +wire [7:0] ic0_cfg; +wire [7:0] ic1_cfg; +wire [7:0] ic2_cfg; +wire [2:0] oc0_int_set; +wire [2:0] oc1_int_set; +wire [2:0] oc2_int_set; +wire [2:0] oc3_int_set; +wire [2:0] oc4_int_set; +wire [2:0] oc5_int_set; +wire [2:0] ic0_int_set; +wire [2:0] ic1_int_set; +wire [2:0] ic2_int_set; + +// CRA Module interface +wire crac_valid; +wire crac_wr; +wire crac_wr_done, crac_rd_done; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// Sync Valid to WISHBONE Clock +always @(posedge clk_i) + valid_s1 <= #1 valid; + +always @(posedge clk_i) + valid_s <= #1 valid_s1; + +always @(posedge clk_i) + in_valid_s1 <= #1 in_valid; + +always @(posedge clk_i) + in_valid_s <= #1 in_valid_s1; + +// "valid_s" Indicates when any of the outputs to the output S/R may +// change or when outputs from input S/R may be sampled +assign o3_mode = oc0_cfg[3:2]; +assign o4_mode = oc1_cfg[3:2]; +assign o6_mode = oc2_cfg[3:2]; +assign o7_mode = oc3_cfg[3:2]; +assign o8_mode = oc4_cfg[3:2]; +assign o9_mode = oc5_cfg[3:2]; +assign i3_mode = ic0_cfg[3:2]; +assign i4_mode = ic1_cfg[3:2]; +assign i6_mode = ic2_cfg[3:2]; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +ac97_sout u0( + .clk( bit_clk_pad_i ), + .rst( rst_i ), + .so_ld( ld ), + .slt0( out_slt0 ), + .slt1( out_slt1 ), + .slt2( out_slt2 ), + .slt3( out_slt3 ), + .slt4( out_slt4 ), + .slt6( out_slt6 ), + .slt7( out_slt7 ), + .slt8( out_slt8 ), + .slt9( out_slt9 ), + .sdata_out( sdata_pad_o ) + ); + +ac97_sin u1( + .clk( bit_clk_pad_i ), + .rst( rst_i ), + .out_le( out_le ), + .slt0( in_slt0 ), + .slt1( in_slt1 ), + .slt2( in_slt2 ), + .slt3( in_slt3 ), + .slt4( in_slt4 ), + .slt6( in_slt6 ), + .sdata_in( sdata_pad_i ) + ); + +ac97_soc u2( + .clk( bit_clk_pad_i ), + .wclk( clk_i ), + .rst( rst_i ), + .ps_ce( ps_ce ), + .resume( resume_req ), + .suspended( suspended_o ), + .sync( sync_pad_o ), + .out_le( out_le ), + .in_valid( in_valid ), + .ld( ld ), + .valid( valid ) + ); + +ac97_out_fifo u3( + .clk( clk_i ), + .rst( rst_i ), + .en( oc0_cfg[0] ), + .mode( o3_mode ), + .din( wb_din ), + .we( o3_we ), + .dout( out_slt3 ), + .re( o3_re ), + .status( o3_status ), + .full( o3_full ), + .empty( o3_empty ) + ); + +ac97_out_fifo u4( + .clk( clk_i ), + .rst( rst_i ), + .en( oc1_cfg[0] ), + .mode( o4_mode ), + .din( wb_din ), + .we( o4_we ), + .dout( out_slt4 ), + .re( o4_re ), + .status( o4_status ), + .full( o4_full ), + .empty( o4_empty ) + ); + +`ifdef AC97_CENTER +ac97_out_fifo u5( + .clk( clk_i ), + .rst( rst_i ), + .en( oc2_cfg[0] ), + .mode( o6_mode ), + .din( wb_din ), + .we( o6_we ), + .dout( out_slt6 ), + .re( o6_re ), + .status( o6_status ), + .full( o6_full ), + .empty( o6_empty ) + ); +`else +assign out_slt6 = 20'h0; +assign o6_status = 2'h0; +assign o6_full = 1'b0; +assign o6_empty = 1'b0; +`endif + +`ifdef AC97_SURROUND +ac97_out_fifo u6( + .clk( clk_i ), + .rst( rst_i ), + .en( oc3_cfg[0] ), + .mode( o7_mode ), + .din( wb_din ), + .we( o7_we ), + .dout( out_slt7 ), + .re( o7_re ), + .status( o7_status ), + .full( o7_full ), + .empty( o7_empty ) + ); + +ac97_out_fifo u7( + .clk( clk_i ), + .rst( rst_i ), + .en( oc4_cfg[0] ), + .mode( o8_mode ), + .din( wb_din ), + .we( o8_we ), + .dout( out_slt8 ), + .re( o8_re ), + .status( o8_status ), + .full( o8_full ), + .empty( o8_empty ) + ); +`else +assign out_slt7 = 20'h0; +assign o7_status = 2'h0; +assign o7_full = 1'b0; +assign o7_empty = 1'b0; +assign out_slt8 = 20'h0; +assign o8_status = 2'h0; +assign o8_full = 1'b0; +assign o8_empty = 1'b0; +`endif + +`ifdef AC97_LFE +ac97_out_fifo u8( + .clk( clk_i ), + .rst( rst_i ), + .en( oc5_cfg[0] ), + .mode( o9_mode ), + .din( wb_din ), + .we( o9_we ), + .dout( out_slt9 ), + .re( o9_re ), + .status( o9_status ), + .full( o9_full ), + .empty( o9_empty ) + ); +`else +assign out_slt9 = 20'h0; +assign o9_status = 2'h0; +assign o9_full = 1'b0; +assign o9_empty = 1'b0; +`endif + +`ifdef AC97_SIN +ac97_in_fifo u9( + .clk( clk_i ), + .rst( rst_i ), + .en( ic0_cfg[0] ), + .mode( i3_mode ), + .din( in_slt3 ), + .we( i3_we ), + .dout( i3_dout ), + .re( i3_re ), + .status( i3_status ), + .full( i3_full ), + .empty( i3_empty ) + ); + +ac97_in_fifo u10( + .clk( clk_i ), + .rst( rst_i ), + .en( ic1_cfg[0] ), + .mode( i4_mode ), + .din( in_slt4 ), + .we( i4_we ), + .dout( i4_dout ), + .re( i4_re ), + .status( i4_status ), + .full( i4_full ), + .empty( i4_empty ) + ); +`else +assign i3_dout = 20'h0; +assign i3_status = 2'h0; +assign i3_full = 1'b0; +assign i3_empty = 1'b0; +assign i4_dout = 20'h0; +assign i4_status = 2'h0; +assign i4_full = 1'b0; +assign i4_empty = 1'b0; +`endif + +`ifdef AC97_MICIN +ac97_in_fifo u11( + .clk( clk_i ), + .rst( rst_i ), + .en( ic2_cfg[0] ), + .mode( i6_mode ), + .din( in_slt6 ), + .we( i6_we ), + .dout( i6_dout ), + .re( i6_re ), + .status( i6_status ), + .full( i6_full ), + .empty( i6_empty ) + ); +`else +assign i6_dout = 20'h0; +assign i6_status = 2'h0; +assign i6_full = 1'b0; +assign i6_empty = 1'b0; +`endif + +ac97_wb_if u12( + .clk( clk_i ), + .rst( rst_i ), + .wb_data_i( wb_data_i ), + .wb_data_o( wb_data_o ), + .wb_addr_i( wb_addr_i ), + .wb_sel_i( wb_sel_i ), + .wb_we_i( wb_we_i ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_ack_o( wb_ack_o ), + .wb_err_o( wb_err_o ), + .adr( adr ), + .dout( wb_din ), + .rf_din( rf_dout ), + .i3_din( i3_dout ), + .i4_din( i4_dout ), + .i6_din( i6_dout ), + .rf_we( rf_we ), + .rf_re( rf_re ), + .o3_we( o3_we ), + .o4_we( o4_we ), + .o6_we( o6_we ), + .o7_we( o7_we ), + .o8_we( o8_we ), + .o9_we( o9_we ), + .i3_re( i3_re ), + .i4_re( i4_re ), + .i6_re( i6_re ) + ); + +ac97_rf u13( .clk( clk_i ), + .rst( rst_i ), + .adr( adr ), + .rf_dout( rf_dout ), + .rf_din( wb_din ), + .rf_we( rf_we ), + .rf_re( rf_re ), + .int( int_o ), + .ac97_rst_force(ac97_rst_force ), + .resume_req( resume_req ), + .suspended( suspended_o ), + .crac_we( crac_we ), + .crac_din( crac_din ), + .crac_out( crac_out ), + .crac_wr_done( crac_wr_done ), + .crac_rd_done( crac_rd_done ), + .oc0_cfg( oc0_cfg ), + .oc1_cfg( oc1_cfg ), + .oc2_cfg( oc2_cfg ), + .oc3_cfg( oc3_cfg ), + .oc4_cfg( oc4_cfg ), + .oc5_cfg( oc5_cfg ), + .ic0_cfg( ic0_cfg ), + .ic1_cfg( ic1_cfg ), + .ic2_cfg( ic2_cfg ), + .oc0_int_set( oc0_int_set ), + .oc1_int_set( oc1_int_set ), + .oc2_int_set( oc2_int_set ), + .oc3_int_set( oc3_int_set ), + .oc4_int_set( oc4_int_set ), + .oc5_int_set( oc5_int_set ), + .ic0_int_set( ic0_int_set ), + .ic1_int_set( ic1_int_set ), + .ic2_int_set( ic2_int_set ) + ); + +ac97_prc u14( .clk( clk_i ), + .rst( rst_i ), + .valid( valid_s ), + .in_valid( in_valid_s ), + .out_slt0( out_slt0 ), + .in_slt0( in_slt0 ), + .in_slt1( in_slt1 ), + .crac_valid( crac_valid ), + .crac_wr( crac_wr ), + .oc0_cfg( oc0_cfg ), + .oc1_cfg( oc1_cfg ), + .oc2_cfg( oc2_cfg ), + .oc3_cfg( oc3_cfg ), + .oc4_cfg( oc4_cfg ), + .oc5_cfg( oc5_cfg ), + .ic0_cfg( ic0_cfg ), + .ic1_cfg( ic1_cfg ), + .ic2_cfg( ic2_cfg ), + .o3_empty( o3_empty ), + .o4_empty( o4_empty ), + .o6_empty( o6_empty ), + .o7_empty( o7_empty ), + .o8_empty( o8_empty ), + .o9_empty( o9_empty ), + .i3_full( i3_full ), + .i4_full( i4_full ), + .i6_full( i6_full ), + .o3_re( o3_re ), + .o4_re( o4_re ), + .o6_re( o6_re ), + .o7_re( o7_re ), + .o8_re( o8_re ), + .o9_re( o9_re ), + .i3_we( i3_we ), + .i4_we( i4_we ), + .i6_we( i6_we ) + ); + +ac97_cra u15( .clk( clk_i ), + .rst( rst_i ), + .crac_we( crac_we ), + .crac_din( crac_din ), + .crac_out( crac_out ), + .crac_wr_done( crac_wr_done ), + .crac_rd_done( crac_rd_done ), + .valid( valid_s ), + .out_slt1( out_slt1 ), + .out_slt2( out_slt2 ), + .in_slt2( in_slt2 ), + .crac_valid( crac_valid ), + .crac_wr( crac_wr ) + ); + +ac97_dma_if u16(.clk( clk_i ), + .rst( rst_i ), + .o3_status( o3_status ), + .o4_status( o4_status ), + .o6_status( o6_status ), + .o7_status( o7_status ), + .o8_status( o8_status ), + .o9_status( o9_status ), + .o3_empty( o3_empty ), + .o4_empty( o4_empty ), + .o6_empty( o6_empty ), + .o7_empty( o7_empty ), + .o8_empty( o8_empty ), + .o9_empty( o9_empty ), + .i3_status( i3_status ), + .i4_status( i4_status ), + .i6_status( i6_status ), + .i3_full( i3_full ), + .i4_full( i4_full ), + .i6_full( i6_full ), + .oc0_cfg( oc0_cfg ), + .oc1_cfg( oc1_cfg ), + .oc2_cfg( oc2_cfg ), + .oc3_cfg( oc3_cfg ), + .oc4_cfg( oc4_cfg ), + .oc5_cfg( oc5_cfg ), + .ic0_cfg( ic0_cfg ), + .ic1_cfg( ic1_cfg ), + .ic2_cfg( ic2_cfg ), + .dma_req( dma_req_o ), + .dma_ack( dma_ack_i ) + ); + +ac97_int u17( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc0_int_set ), + .cfg( oc0_cfg ), + .status( o3_status ), + .full_empty( o3_empty ), + .full( o3_full ), + .empty( o3_empty ), + .re( o3_re ), + .we( o3_we ) + ); + +ac97_int u18( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc1_int_set ), + .cfg( oc1_cfg ), + .status( o4_status ), + .full_empty( o4_empty ), + .full( o4_full ), + .empty( o4_empty ), + .re( o4_re ), + .we( o4_we ) + ); + +`ifdef AC97_CENTER +ac97_int u19( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc2_int_set ), + .cfg( oc2_cfg ), + .status( o6_status ), + .full_empty( o6_empty ), + .full( o6_full ), + .empty( o6_empty ), + .re( o6_re ), + .we( o6_we ) + ); +`else +assign oc2_int_set = 1'b0; +`endif + +`ifdef AC97_SURROUND +ac97_int u20( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc3_int_set ), + .cfg( oc3_cfg ), + .status( o7_status ), + .full_empty( o7_empty ), + .full( o7_full ), + .empty( o7_empty ), + .re( o7_re ), + .we( o7_we ) + ); + +ac97_int u21( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc4_int_set ), + .cfg( oc4_cfg ), + .status( o8_status ), + .full_empty( o8_empty ), + .full( o8_full ), + .empty( o8_empty ), + .re( o8_re ), + .we( o8_we ) + ); +`else +assign oc3_int_set = 1'b0; +assign oc4_int_set = 1'b0; +`endif + +`ifdef AC97_LFE +ac97_int u22( + .clk( clk_i ), + .rst( rst_i ), + .int_set( oc5_int_set ), + .cfg( oc5_cfg ), + .status( o9_status ), + .full_empty( o9_empty ), + .full( o9_full ), + .empty( o9_empty ), + .re( o9_re ), + .we( o9_we ) + ); +`else +assign oc5_int_set = 1'b0; +`endif + +`ifdef AC97_SIN +ac97_int u23( + .clk( clk_i ), + .rst( rst_i ), + .int_set( ic0_int_set ), + .cfg( ic0_cfg ), + .status( i3_status ), + .full_empty( i3_full ), + .full( i3_full ), + .empty( i3_empty ), + .re( i3_re ), + .we( i3_we ) + ); + +ac97_int u24( + .clk( clk_i ), + .rst( rst_i ), + .int_set( ic1_int_set ), + .cfg( ic1_cfg ), + .status( i4_status ), + .full_empty( i4_full ), + .full( i4_full ), + .empty( i4_empty ), + .re( i4_re ), + .we( i4_we ) + ); +`else +assign ic0_int_set = 1'b0; +assign ic1_int_set = 1'b0; +`endif + +`ifdef AC97_MICIN +ac97_int u25( + .clk( clk_i ), + .rst( rst_i ), + .int_set( ic2_int_set ), + .cfg( ic2_cfg ), + .status( i6_status ), + .full_empty( i6_full ), + .full( i6_full ), + .empty( i6_empty ), + .re( i6_re ), + .we( i6_we ) + ); +`else +assign ic2_int_set = 1'b0; +`endif + +ac97_rst u26( + .clk( clk_i ), + .rst( rst_i ), + .rst_force( ac97_rst_force ), + .ps_ce( ps_ce ), + .ac97_rst_( ac97_reset_pad_o_ ) + ); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v new file mode 100644 index 000000000..aa9ed8156 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v @@ -0,0 +1,204 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// WISHBONE Interface Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: ac97_wb_if.v,v 1.4 2002/09/19 06:30:56 rudi Exp $ +// +// $Date: 2002/09/19 06:30:56 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: ac97_wb_if.v,v $ +// Revision 1.4 2002/09/19 06:30:56 rudi +// Fixed a bug reported by Igor. Apparently this bug only shows up when +// the WB clock is very low (2x bit_clk). Updated Copyright header. +// +// Revision 1.3 2002/03/05 04:44:05 rudi +// +// - Fixed the order of the thrash hold bits to match the spec. +// - Many minor synthesis cleanup items ... +// +// Revision 1.2 2001/08/10 08:09:42 rudi +// +// - Removed RTY_O output. +// - Added Clock and Reset Inputs to documentation. +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 06:54:50 rudi +// +// +// - Changed to new directory structure +// +// Revision 1.1.1.1 2001/05/19 02:29:16 rudi +// Initial Checkin +// +// +// +// + +`include "ac97_defines.v" + +module ac97_wb_if(clk, rst, + + wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, + + adr, dout, rf_din, i3_din, i4_din, i6_din, + rf_we, rf_re, o3_we, o4_we, o6_we, o7_we, o8_we, o9_we, + i3_re, i4_re, i6_re + + ); + +input clk,rst; + +// WISHBONE Interface +input [31:0] wb_data_i; +output [31:0] wb_data_o; +input [31:0] wb_addr_i; +input [3:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; + +// Internal Interface +output [3:0] adr; +output [31:0] dout; +input [31:0] rf_din, i3_din, i4_din, i6_din; +output rf_we; +output rf_re; +output o3_we, o4_we, o6_we, o7_we, o8_we, o9_we; +output i3_re, i4_re, i6_re; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [31:0] wb_data_o; +reg [31:0] dout; +reg wb_ack_o; + +reg rf_we; +reg o3_we, o4_we, o6_we, o7_we, o8_we, o9_we; +reg i3_re, i4_re, i6_re; + +reg we1, we2; +wire we; +reg re2, re1; +wire re; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +assign adr = wb_addr_i[5:2]; + +assign wb_err_o = 1'b0; + +always @(posedge clk) + dout <= #1 wb_data_i; + +always @(posedge clk) + case(wb_addr_i[6:2]) // synopsys parallel_case full_case + 5'he: wb_data_o <= #1 i3_din; + 5'hf: wb_data_o <= #1 i4_din; + 5'h10: wb_data_o <= #1 i6_din; + default: wb_data_o <= #1 rf_din; + endcase + +always @(posedge clk) + re1 <= #1 !re2 & wb_cyc_i & wb_stb_i & !wb_we_i & `AC97_REG_SEL; + +always @(posedge clk) + re2 <= #1 re & wb_cyc_i & wb_stb_i & !wb_we_i ; + +assign re = re1 & !re2 & wb_cyc_i & wb_stb_i & !wb_we_i; + +assign rf_re = re & (wb_addr_i[6:2] < 5'h8); + +always @(posedge clk) + we1 <= #1 !we & wb_cyc_i & wb_stb_i & wb_we_i & `AC97_REG_SEL; + +always @(posedge clk) + we2 <= #1 we1 & wb_cyc_i & wb_stb_i & wb_we_i; + +assign we = we1 & !we2 & wb_cyc_i & wb_stb_i & wb_we_i; + +always @(posedge clk) + wb_ack_o <= #1 (re | we) & wb_cyc_i & wb_stb_i & ~wb_ack_o; + +always @(posedge clk) + rf_we <= #1 we & (wb_addr_i[6:2] < 5'h8); + +always @(posedge clk) + o3_we <= #1 we & (wb_addr_i[6:2] == 5'h8); + +always @(posedge clk) + o4_we <= #1 we & (wb_addr_i[6:2] == 5'h9); + +always @(posedge clk) + o6_we <= #1 we & (wb_addr_i[6:2] == 5'ha); + +always @(posedge clk) + o7_we <= #1 we & (wb_addr_i[6:2] == 5'hb); + +always @(posedge clk) + o8_we <= #1 we & (wb_addr_i[6:2] == 5'hc); + +always @(posedge clk) + o9_we <= #1 we & (wb_addr_i[6:2] == 5'hd); + +always @(posedge clk) + i3_re <= #1 re & (wb_addr_i[6:2] == 5'he); + +always @(posedge clk) + i4_re <= #1 re & (wb_addr_i[6:2] == 5'hf); + +always @(posedge clk) + i6_re <= #1 re & (wb_addr_i[6:2] == 5'h10); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v new file mode 100644 index 000000000..a0acaeb48 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v @@ -0,0 +1,256 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Cipher Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_cipher_top.v,v 1.1.1.1 2002/11/09 11:22:48 rudi Exp $ +// +// $Date: 2002/11/09 11:22:48 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_cipher_top.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:48 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_cipher_top(clk, rst, ld, done, key, text_in, text_out ); +input clk, rst; +input ld; +output done; +input [127:0] key; +input [127:0] text_in; +output [127:0] text_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [31:0] w0, w1, w2, w3; +reg [127:0] text_in_r; +reg [127:0] text_out; +reg [7:0] sa00, sa01, sa02, sa03; +reg [7:0] sa10, sa11, sa12, sa13; +reg [7:0] sa20, sa21, sa22, sa23; +reg [7:0] sa30, sa31, sa32, sa33; +wire [7:0] sa00_next, sa01_next, sa02_next, sa03_next; +wire [7:0] sa10_next, sa11_next, sa12_next, sa13_next; +wire [7:0] sa20_next, sa21_next, sa22_next, sa23_next; +wire [7:0] sa30_next, sa31_next, sa32_next, sa33_next; +wire [7:0] sa00_sub, sa01_sub, sa02_sub, sa03_sub; +wire [7:0] sa10_sub, sa11_sub, sa12_sub, sa13_sub; +wire [7:0] sa20_sub, sa21_sub, sa22_sub, sa23_sub; +wire [7:0] sa30_sub, sa31_sub, sa32_sub, sa33_sub; +wire [7:0] sa00_sr, sa01_sr, sa02_sr, sa03_sr; +wire [7:0] sa10_sr, sa11_sr, sa12_sr, sa13_sr; +wire [7:0] sa20_sr, sa21_sr, sa22_sr, sa23_sr; +wire [7:0] sa30_sr, sa31_sr, sa32_sr, sa33_sr; +wire [7:0] sa00_mc, sa01_mc, sa02_mc, sa03_mc; +wire [7:0] sa10_mc, sa11_mc, sa12_mc, sa13_mc; +wire [7:0] sa20_mc, sa21_mc, sa22_mc, sa23_mc; +wire [7:0] sa30_mc, sa31_mc, sa32_mc, sa33_mc; +reg done, ld_r; +reg [3:0] dcnt; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + if(!rst) dcnt <= #1 4'h0; + else + if(ld) dcnt <= #1 4'hb; + else + if(|dcnt) dcnt <= #1 dcnt - 4'h1; + +always @(posedge clk) done <= #1 !(|dcnt[3:1]) & dcnt[0] & !ld; +always @(posedge clk) if(ld) text_in_r <= #1 text_in; +always @(posedge clk) ld_r <= #1 ld; + +//////////////////////////////////////////////////////////////////// +// +// Initial Permutation (AddRoundKey) +// + +always @(posedge clk) sa33 <= #1 ld_r ? text_in_r[007:000] ^ w3[07:00] : sa33_next; +always @(posedge clk) sa23 <= #1 ld_r ? text_in_r[015:008] ^ w3[15:08] : sa23_next; +always @(posedge clk) sa13 <= #1 ld_r ? text_in_r[023:016] ^ w3[23:16] : sa13_next; +always @(posedge clk) sa03 <= #1 ld_r ? text_in_r[031:024] ^ w3[31:24] : sa03_next; +always @(posedge clk) sa32 <= #1 ld_r ? text_in_r[039:032] ^ w2[07:00] : sa32_next; +always @(posedge clk) sa22 <= #1 ld_r ? text_in_r[047:040] ^ w2[15:08] : sa22_next; +always @(posedge clk) sa12 <= #1 ld_r ? text_in_r[055:048] ^ w2[23:16] : sa12_next; +always @(posedge clk) sa02 <= #1 ld_r ? text_in_r[063:056] ^ w2[31:24] : sa02_next; +always @(posedge clk) sa31 <= #1 ld_r ? text_in_r[071:064] ^ w1[07:00] : sa31_next; +always @(posedge clk) sa21 <= #1 ld_r ? text_in_r[079:072] ^ w1[15:08] : sa21_next; +always @(posedge clk) sa11 <= #1 ld_r ? text_in_r[087:080] ^ w1[23:16] : sa11_next; +always @(posedge clk) sa01 <= #1 ld_r ? text_in_r[095:088] ^ w1[31:24] : sa01_next; +always @(posedge clk) sa30 <= #1 ld_r ? text_in_r[103:096] ^ w0[07:00] : sa30_next; +always @(posedge clk) sa20 <= #1 ld_r ? text_in_r[111:104] ^ w0[15:08] : sa20_next; +always @(posedge clk) sa10 <= #1 ld_r ? text_in_r[119:112] ^ w0[23:16] : sa10_next; +always @(posedge clk) sa00 <= #1 ld_r ? text_in_r[127:120] ^ w0[31:24] : sa00_next; + +//////////////////////////////////////////////////////////////////// +// +// Round Permutations +// + +assign sa00_sr = sa00_sub; +assign sa01_sr = sa01_sub; +assign sa02_sr = sa02_sub; +assign sa03_sr = sa03_sub; +assign sa10_sr = sa11_sub; +assign sa11_sr = sa12_sub; +assign sa12_sr = sa13_sub; +assign sa13_sr = sa10_sub; +assign sa20_sr = sa22_sub; +assign sa21_sr = sa23_sub; +assign sa22_sr = sa20_sub; +assign sa23_sr = sa21_sub; +assign sa30_sr = sa33_sub; +assign sa31_sr = sa30_sub; +assign sa32_sr = sa31_sub; +assign sa33_sr = sa32_sub; +assign {sa00_mc, sa10_mc, sa20_mc, sa30_mc} = mix_col(sa00_sr,sa10_sr,sa20_sr,sa30_sr); +assign {sa01_mc, sa11_mc, sa21_mc, sa31_mc} = mix_col(sa01_sr,sa11_sr,sa21_sr,sa31_sr); +assign {sa02_mc, sa12_mc, sa22_mc, sa32_mc} = mix_col(sa02_sr,sa12_sr,sa22_sr,sa32_sr); +assign {sa03_mc, sa13_mc, sa23_mc, sa33_mc} = mix_col(sa03_sr,sa13_sr,sa23_sr,sa33_sr); +assign sa00_next = sa00_mc ^ w0[31:24]; +assign sa01_next = sa01_mc ^ w1[31:24]; +assign sa02_next = sa02_mc ^ w2[31:24]; +assign sa03_next = sa03_mc ^ w3[31:24]; +assign sa10_next = sa10_mc ^ w0[23:16]; +assign sa11_next = sa11_mc ^ w1[23:16]; +assign sa12_next = sa12_mc ^ w2[23:16]; +assign sa13_next = sa13_mc ^ w3[23:16]; +assign sa20_next = sa20_mc ^ w0[15:08]; +assign sa21_next = sa21_mc ^ w1[15:08]; +assign sa22_next = sa22_mc ^ w2[15:08]; +assign sa23_next = sa23_mc ^ w3[15:08]; +assign sa30_next = sa30_mc ^ w0[07:00]; +assign sa31_next = sa31_mc ^ w1[07:00]; +assign sa32_next = sa32_mc ^ w2[07:00]; +assign sa33_next = sa33_mc ^ w3[07:00]; + +//////////////////////////////////////////////////////////////////// +// +// Final text output +// + +always @(posedge clk) text_out[127:120] <= #1 sa00_sr ^ w0[31:24]; +always @(posedge clk) text_out[095:088] <= #1 sa01_sr ^ w1[31:24]; +always @(posedge clk) text_out[063:056] <= #1 sa02_sr ^ w2[31:24]; +always @(posedge clk) text_out[031:024] <= #1 sa03_sr ^ w3[31:24]; +always @(posedge clk) text_out[119:112] <= #1 sa10_sr ^ w0[23:16]; +always @(posedge clk) text_out[087:080] <= #1 sa11_sr ^ w1[23:16]; +always @(posedge clk) text_out[055:048] <= #1 sa12_sr ^ w2[23:16]; +always @(posedge clk) text_out[023:016] <= #1 sa13_sr ^ w3[23:16]; +always @(posedge clk) text_out[111:104] <= #1 sa20_sr ^ w0[15:08]; +always @(posedge clk) text_out[079:072] <= #1 sa21_sr ^ w1[15:08]; +always @(posedge clk) text_out[047:040] <= #1 sa22_sr ^ w2[15:08]; +always @(posedge clk) text_out[015:008] <= #1 sa23_sr ^ w3[15:08]; +always @(posedge clk) text_out[103:096] <= #1 sa30_sr ^ w0[07:00]; +always @(posedge clk) text_out[071:064] <= #1 sa31_sr ^ w1[07:00]; +always @(posedge clk) text_out[039:032] <= #1 sa32_sr ^ w2[07:00]; +always @(posedge clk) text_out[007:000] <= #1 sa33_sr ^ w3[07:00]; + +//////////////////////////////////////////////////////////////////// +// +// Generic Functions +// + +function [31:0] mix_col; +input [7:0] s0,s1,s2,s3; +reg [7:0] s0_o,s1_o,s2_o,s3_o; +begin +mix_col[31:24]=xtime(s0)^xtime(s1)^s1^s2^s3; +mix_col[23:16]=s0^xtime(s1)^xtime(s2)^s2^s3; +mix_col[15:08]=s0^s1^xtime(s2)^xtime(s3)^s3; +mix_col[07:00]=xtime(s0)^s0^s1^s2^xtime(s3); +end +endfunction + +function [7:0] xtime; +input [7:0] b; xtime={b[6:0],1'b0}^(8'h1b&{8{b[7]}}); +endfunction + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +aes_key_expand_128 u0( + .clk( clk ), + .kld( ld ), + .key( key ), + .wo_0( w0 ), + .wo_1( w1 ), + .wo_2( w2 ), + .wo_3( w3 )); + +aes_sbox us00( .a( sa00 ), .d( sa00_sub )); +aes_sbox us01( .a( sa01 ), .d( sa01_sub )); +aes_sbox us02( .a( sa02 ), .d( sa02_sub )); +aes_sbox us03( .a( sa03 ), .d( sa03_sub )); +aes_sbox us10( .a( sa10 ), .d( sa10_sub )); +aes_sbox us11( .a( sa11 ), .d( sa11_sub )); +aes_sbox us12( .a( sa12 ), .d( sa12_sub )); +aes_sbox us13( .a( sa13 ), .d( sa13_sub )); +aes_sbox us20( .a( sa20 ), .d( sa20_sub )); +aes_sbox us21( .a( sa21 ), .d( sa21_sub )); +aes_sbox us22( .a( sa22 ), .d( sa22_sub )); +aes_sbox us23( .a( sa23 ), .d( sa23_sub )); +aes_sbox us30( .a( sa30 ), .d( sa30_sub )); +aes_sbox us31( .a( sa31 ), .d( sa31_sub )); +aes_sbox us32( .a( sa32 ), .d( sa32_sub )); +aes_sbox us33( .a( sa33 ), .d( sa33_sub )); + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v new file mode 100644 index 000000000..51b3525ac --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v @@ -0,0 +1,327 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Inverse Cipher Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_inv_cipher_top.v,v 1.1.1.1 2002/11/09 11:22:53 rudi Exp $ +// +// $Date: 2002/11/09 11:22:53 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_inv_cipher_top.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:53 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_inv_cipher_top(clk, rst, kld, ld, done, key, text_in, text_out ); +input clk, rst; +input kld, ld; +output done; +input [127:0] key; +input [127:0] text_in; +output [127:0] text_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [31:0] wk0, wk1, wk2, wk3; +reg [31:0] w0, w1, w2, w3; +reg [127:0] text_in_r; +reg [127:0] text_out; +reg [7:0] sa00, sa01, sa02, sa03; +reg [7:0] sa10, sa11, sa12, sa13; +reg [7:0] sa20, sa21, sa22, sa23; +reg [7:0] sa30, sa31, sa32, sa33; +wire [7:0] sa00_next, sa01_next, sa02_next, sa03_next; +wire [7:0] sa10_next, sa11_next, sa12_next, sa13_next; +wire [7:0] sa20_next, sa21_next, sa22_next, sa23_next; +wire [7:0] sa30_next, sa31_next, sa32_next, sa33_next; +wire [7:0] sa00_sub, sa01_sub, sa02_sub, sa03_sub; +wire [7:0] sa10_sub, sa11_sub, sa12_sub, sa13_sub; +wire [7:0] sa20_sub, sa21_sub, sa22_sub, sa23_sub; +wire [7:0] sa30_sub, sa31_sub, sa32_sub, sa33_sub; +wire [7:0] sa00_sr, sa01_sr, sa02_sr, sa03_sr; +wire [7:0] sa10_sr, sa11_sr, sa12_sr, sa13_sr; +wire [7:0] sa20_sr, sa21_sr, sa22_sr, sa23_sr; +wire [7:0] sa30_sr, sa31_sr, sa32_sr, sa33_sr; +wire [7:0] sa00_ark, sa01_ark, sa02_ark, sa03_ark; +wire [7:0] sa10_ark, sa11_ark, sa12_ark, sa13_ark; +wire [7:0] sa20_ark, sa21_ark, sa22_ark, sa23_ark; +wire [7:0] sa30_ark, sa31_ark, sa32_ark, sa33_ark; +reg ld_r, go, done; +reg [3:0] dcnt; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + if(!rst) dcnt <= #1 4'h0; + else + if(done) dcnt <= #1 4'h0; + else + if(ld) dcnt <= #1 4'h1; + else + if(go) dcnt <= #1 dcnt + 4'h1; + +always @(posedge clk) done <= #1 (dcnt==4'hb) & !ld; + +always @(posedge clk) + if(!rst) go <= #1 1'b0; + else + if(ld) go <= #1 1'b1; + else + if(done) go <= #1 1'b0; + +always @(posedge clk) if(ld) text_in_r <= #1 text_in; + +always @(posedge clk) ld_r <= #1 ld; + +//////////////////////////////////////////////////////////////////// +// +// Initial Permutation +// + +always @(posedge clk) sa33 <= #1 ld_r ? text_in_r[007:000] ^ w3[07:00] : sa33_next; +always @(posedge clk) sa23 <= #1 ld_r ? text_in_r[015:008] ^ w3[15:08] : sa23_next; +always @(posedge clk) sa13 <= #1 ld_r ? text_in_r[023:016] ^ w3[23:16] : sa13_next; +always @(posedge clk) sa03 <= #1 ld_r ? text_in_r[031:024] ^ w3[31:24] : sa03_next; +always @(posedge clk) sa32 <= #1 ld_r ? text_in_r[039:032] ^ w2[07:00] : sa32_next; +always @(posedge clk) sa22 <= #1 ld_r ? text_in_r[047:040] ^ w2[15:08] : sa22_next; +always @(posedge clk) sa12 <= #1 ld_r ? text_in_r[055:048] ^ w2[23:16] : sa12_next; +always @(posedge clk) sa02 <= #1 ld_r ? text_in_r[063:056] ^ w2[31:24] : sa02_next; +always @(posedge clk) sa31 <= #1 ld_r ? text_in_r[071:064] ^ w1[07:00] : sa31_next; +always @(posedge clk) sa21 <= #1 ld_r ? text_in_r[079:072] ^ w1[15:08] : sa21_next; +always @(posedge clk) sa11 <= #1 ld_r ? text_in_r[087:080] ^ w1[23:16] : sa11_next; +always @(posedge clk) sa01 <= #1 ld_r ? text_in_r[095:088] ^ w1[31:24] : sa01_next; +always @(posedge clk) sa30 <= #1 ld_r ? text_in_r[103:096] ^ w0[07:00] : sa30_next; +always @(posedge clk) sa20 <= #1 ld_r ? text_in_r[111:104] ^ w0[15:08] : sa20_next; +always @(posedge clk) sa10 <= #1 ld_r ? text_in_r[119:112] ^ w0[23:16] : sa10_next; +always @(posedge clk) sa00 <= #1 ld_r ? text_in_r[127:120] ^ w0[31:24] : sa00_next; + +//////////////////////////////////////////////////////////////////// +// +// Round Permutations +// + +assign sa00_sr = sa00; +assign sa01_sr = sa01; +assign sa02_sr = sa02; +assign sa03_sr = sa03; +assign sa10_sr = sa13; +assign sa11_sr = sa10; +assign sa12_sr = sa11; +assign sa13_sr = sa12; +assign sa20_sr = sa22; +assign sa21_sr = sa23; +assign sa22_sr = sa20; +assign sa23_sr = sa21; +assign sa30_sr = sa31; +assign sa31_sr = sa32; +assign sa32_sr = sa33; +assign sa33_sr = sa30; +assign sa00_ark = sa00_sub ^ w0[31:24]; +assign sa01_ark = sa01_sub ^ w1[31:24]; +assign sa02_ark = sa02_sub ^ w2[31:24]; +assign sa03_ark = sa03_sub ^ w3[31:24]; +assign sa10_ark = sa10_sub ^ w0[23:16]; +assign sa11_ark = sa11_sub ^ w1[23:16]; +assign sa12_ark = sa12_sub ^ w2[23:16]; +assign sa13_ark = sa13_sub ^ w3[23:16]; +assign sa20_ark = sa20_sub ^ w0[15:08]; +assign sa21_ark = sa21_sub ^ w1[15:08]; +assign sa22_ark = sa22_sub ^ w2[15:08]; +assign sa23_ark = sa23_sub ^ w3[15:08]; +assign sa30_ark = sa30_sub ^ w0[07:00]; +assign sa31_ark = sa31_sub ^ w1[07:00]; +assign sa32_ark = sa32_sub ^ w2[07:00]; +assign sa33_ark = sa33_sub ^ w3[07:00]; +assign {sa00_next, sa10_next, sa20_next, sa30_next} = inv_mix_col(sa00_ark,sa10_ark,sa20_ark,sa30_ark); +assign {sa01_next, sa11_next, sa21_next, sa31_next} = inv_mix_col(sa01_ark,sa11_ark,sa21_ark,sa31_ark); +assign {sa02_next, sa12_next, sa22_next, sa32_next} = inv_mix_col(sa02_ark,sa12_ark,sa22_ark,sa32_ark); +assign {sa03_next, sa13_next, sa23_next, sa33_next} = inv_mix_col(sa03_ark,sa13_ark,sa23_ark,sa33_ark); + +//////////////////////////////////////////////////////////////////// +// +// Final Text Output +// + +always @(posedge clk) text_out[127:120] <= #1 sa00_ark; +always @(posedge clk) text_out[095:088] <= #1 sa01_ark; +always @(posedge clk) text_out[063:056] <= #1 sa02_ark; +always @(posedge clk) text_out[031:024] <= #1 sa03_ark; +always @(posedge clk) text_out[119:112] <= #1 sa10_ark; +always @(posedge clk) text_out[087:080] <= #1 sa11_ark; +always @(posedge clk) text_out[055:048] <= #1 sa12_ark; +always @(posedge clk) text_out[023:016] <= #1 sa13_ark; +always @(posedge clk) text_out[111:104] <= #1 sa20_ark; +always @(posedge clk) text_out[079:072] <= #1 sa21_ark; +always @(posedge clk) text_out[047:040] <= #1 sa22_ark; +always @(posedge clk) text_out[015:008] <= #1 sa23_ark; +always @(posedge clk) text_out[103:096] <= #1 sa30_ark; +always @(posedge clk) text_out[071:064] <= #1 sa31_ark; +always @(posedge clk) text_out[039:032] <= #1 sa32_ark; +always @(posedge clk) text_out[007:000] <= #1 sa33_ark; + +//////////////////////////////////////////////////////////////////// +// +// Generic Functions +// + +function [31:0] inv_mix_col; +input [7:0] s0,s1,s2,s3; +begin +inv_mix_col[31:24]=pmul_e(s0)^pmul_b(s1)^pmul_d(s2)^pmul_9(s3); +inv_mix_col[23:16]=pmul_9(s0)^pmul_e(s1)^pmul_b(s2)^pmul_d(s3); +inv_mix_col[15:08]=pmul_d(s0)^pmul_9(s1)^pmul_e(s2)^pmul_b(s3); +inv_mix_col[07:00]=pmul_b(s0)^pmul_d(s1)^pmul_9(s2)^pmul_e(s3); +end +endfunction + +// Some synthesis tools don't like xtime being called recursevly ... +function [7:0] pmul_e; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_e=eight^four^two; +end +endfunction + +function [7:0] pmul_9; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_9=eight^b; +end +endfunction + +function [7:0] pmul_d; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_d=eight^four^b; +end +endfunction + +function [7:0] pmul_b; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_b=eight^two^b; +end +endfunction + +function [7:0] xtime; +input [7:0] b;xtime={b[6:0],1'b0}^(8'h1b&{8{b[7]}}); +endfunction + +//////////////////////////////////////////////////////////////////// +// +// Key Buffer +// + +reg [127:0] kb[10:0]; +reg [3:0] kcnt; +reg kdone; +reg kb_ld; + +always @(posedge clk) + if(!rst) kcnt <= #1 4'ha; + else + if(kld) kcnt <= #1 4'ha; + else + if(kb_ld) kcnt <= #1 kcnt - 4'h1; + +always @(posedge clk) + if(!rst) kb_ld <= #1 1'b0; + else + if(kld) kb_ld <= #1 1'b1; + else + if(kcnt==4'h0) kb_ld <= #1 1'b0; + +always @(posedge clk) kdone <= #1 (kcnt==4'h0) & !kld; +always @(posedge clk) if(kb_ld) kb[kcnt] <= #1 {wk3, wk2, wk1, wk0}; +always @(posedge clk) {w3, w2, w1, w0} <= #1 kb[dcnt]; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +aes_key_expand_128 u0( + .clk( clk ), + .kld( kld ), + .key( key ), + .wo_0( wk0 ), + .wo_1( wk1 ), + .wo_2( wk2 ), + .wo_3( wk3 )); + +aes_inv_sbox us00( .a( sa00_sr ), .d( sa00_sub )); +aes_inv_sbox us01( .a( sa01_sr ), .d( sa01_sub )); +aes_inv_sbox us02( .a( sa02_sr ), .d( sa02_sub )); +aes_inv_sbox us03( .a( sa03_sr ), .d( sa03_sub )); +aes_inv_sbox us10( .a( sa10_sr ), .d( sa10_sub )); +aes_inv_sbox us11( .a( sa11_sr ), .d( sa11_sub )); +aes_inv_sbox us12( .a( sa12_sr ), .d( sa12_sub )); +aes_inv_sbox us13( .a( sa13_sr ), .d( sa13_sub )); +aes_inv_sbox us20( .a( sa20_sr ), .d( sa20_sub )); +aes_inv_sbox us21( .a( sa21_sr ), .d( sa21_sub )); +aes_inv_sbox us22( .a( sa22_sr ), .d( sa22_sub )); +aes_inv_sbox us23( .a( sa23_sr ), .d( sa23_sub )); +aes_inv_sbox us30( .a( sa30_sr ), .d( sa30_sub )); +aes_inv_sbox us31( .a( sa31_sr ), .d( sa31_sub )); +aes_inv_sbox us32( .a( sa32_sr ), .d( sa32_sub )); +aes_inv_sbox us33( .a( sa33_sr ), .d( sa33_sub )); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v new file mode 100644 index 000000000..323181eba --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v @@ -0,0 +1,328 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Inverse SBOX (ROM) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_inv_sbox.v,v 1.1.1.1 2002/11/09 11:22:55 rudi Exp $ +// +// $Date: 2002/11/09 11:22:55 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_inv_sbox.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:55 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_inv_sbox(a,d); +input [7:0] a; +output [7:0] d; +reg [7:0] d; + +always @(a) + case(a) // synopsys full_case parallel_case + 8'h00: d=8'h52; + 8'h01: d=8'h09; + 8'h02: d=8'h6a; + 8'h03: d=8'hd5; + 8'h04: d=8'h30; + 8'h05: d=8'h36; + 8'h06: d=8'ha5; + 8'h07: d=8'h38; + 8'h08: d=8'hbf; + 8'h09: d=8'h40; + 8'h0a: d=8'ha3; + 8'h0b: d=8'h9e; + 8'h0c: d=8'h81; + 8'h0d: d=8'hf3; + 8'h0e: d=8'hd7; + 8'h0f: d=8'hfb; + 8'h10: d=8'h7c; + 8'h11: d=8'he3; + 8'h12: d=8'h39; + 8'h13: d=8'h82; + 8'h14: d=8'h9b; + 8'h15: d=8'h2f; + 8'h16: d=8'hff; + 8'h17: d=8'h87; + 8'h18: d=8'h34; + 8'h19: d=8'h8e; + 8'h1a: d=8'h43; + 8'h1b: d=8'h44; + 8'h1c: d=8'hc4; + 8'h1d: d=8'hde; + 8'h1e: d=8'he9; + 8'h1f: d=8'hcb; + 8'h20: d=8'h54; + 8'h21: d=8'h7b; + 8'h22: d=8'h94; + 8'h23: d=8'h32; + 8'h24: d=8'ha6; + 8'h25: d=8'hc2; + 8'h26: d=8'h23; + 8'h27: d=8'h3d; + 8'h28: d=8'hee; + 8'h29: d=8'h4c; + 8'h2a: d=8'h95; + 8'h2b: d=8'h0b; + 8'h2c: d=8'h42; + 8'h2d: d=8'hfa; + 8'h2e: d=8'hc3; + 8'h2f: d=8'h4e; + 8'h30: d=8'h08; + 8'h31: d=8'h2e; + 8'h32: d=8'ha1; + 8'h33: d=8'h66; + 8'h34: d=8'h28; + 8'h35: d=8'hd9; + 8'h36: d=8'h24; + 8'h37: d=8'hb2; + 8'h38: d=8'h76; + 8'h39: d=8'h5b; + 8'h3a: d=8'ha2; + 8'h3b: d=8'h49; + 8'h3c: d=8'h6d; + 8'h3d: d=8'h8b; + 8'h3e: d=8'hd1; + 8'h3f: d=8'h25; + 8'h40: d=8'h72; + 8'h41: d=8'hf8; + 8'h42: d=8'hf6; + 8'h43: d=8'h64; + 8'h44: d=8'h86; + 8'h45: d=8'h68; + 8'h46: d=8'h98; + 8'h47: d=8'h16; + 8'h48: d=8'hd4; + 8'h49: d=8'ha4; + 8'h4a: d=8'h5c; + 8'h4b: d=8'hcc; + 8'h4c: d=8'h5d; + 8'h4d: d=8'h65; + 8'h4e: d=8'hb6; + 8'h4f: d=8'h92; + 8'h50: d=8'h6c; + 8'h51: d=8'h70; + 8'h52: d=8'h48; + 8'h53: d=8'h50; + 8'h54: d=8'hfd; + 8'h55: d=8'hed; + 8'h56: d=8'hb9; + 8'h57: d=8'hda; + 8'h58: d=8'h5e; + 8'h59: d=8'h15; + 8'h5a: d=8'h46; + 8'h5b: d=8'h57; + 8'h5c: d=8'ha7; + 8'h5d: d=8'h8d; + 8'h5e: d=8'h9d; + 8'h5f: d=8'h84; + 8'h60: d=8'h90; + 8'h61: d=8'hd8; + 8'h62: d=8'hab; + 8'h63: d=8'h00; + 8'h64: d=8'h8c; + 8'h65: d=8'hbc; + 8'h66: d=8'hd3; + 8'h67: d=8'h0a; + 8'h68: d=8'hf7; + 8'h69: d=8'he4; + 8'h6a: d=8'h58; + 8'h6b: d=8'h05; + 8'h6c: d=8'hb8; + 8'h6d: d=8'hb3; + 8'h6e: d=8'h45; + 8'h6f: d=8'h06; + 8'h70: d=8'hd0; + 8'h71: d=8'h2c; + 8'h72: d=8'h1e; + 8'h73: d=8'h8f; + 8'h74: d=8'hca; + 8'h75: d=8'h3f; + 8'h76: d=8'h0f; + 8'h77: d=8'h02; + 8'h78: d=8'hc1; + 8'h79: d=8'haf; + 8'h7a: d=8'hbd; + 8'h7b: d=8'h03; + 8'h7c: d=8'h01; + 8'h7d: d=8'h13; + 8'h7e: d=8'h8a; + 8'h7f: d=8'h6b; + 8'h80: d=8'h3a; + 8'h81: d=8'h91; + 8'h82: d=8'h11; + 8'h83: d=8'h41; + 8'h84: d=8'h4f; + 8'h85: d=8'h67; + 8'h86: d=8'hdc; + 8'h87: d=8'hea; + 8'h88: d=8'h97; + 8'h89: d=8'hf2; + 8'h8a: d=8'hcf; + 8'h8b: d=8'hce; + 8'h8c: d=8'hf0; + 8'h8d: d=8'hb4; + 8'h8e: d=8'he6; + 8'h8f: d=8'h73; + 8'h90: d=8'h96; + 8'h91: d=8'hac; + 8'h92: d=8'h74; + 8'h93: d=8'h22; + 8'h94: d=8'he7; + 8'h95: d=8'had; + 8'h96: d=8'h35; + 8'h97: d=8'h85; + 8'h98: d=8'he2; + 8'h99: d=8'hf9; + 8'h9a: d=8'h37; + 8'h9b: d=8'he8; + 8'h9c: d=8'h1c; + 8'h9d: d=8'h75; + 8'h9e: d=8'hdf; + 8'h9f: d=8'h6e; + 8'ha0: d=8'h47; + 8'ha1: d=8'hf1; + 8'ha2: d=8'h1a; + 8'ha3: d=8'h71; + 8'ha4: d=8'h1d; + 8'ha5: d=8'h29; + 8'ha6: d=8'hc5; + 8'ha7: d=8'h89; + 8'ha8: d=8'h6f; + 8'ha9: d=8'hb7; + 8'haa: d=8'h62; + 8'hab: d=8'h0e; + 8'hac: d=8'haa; + 8'had: d=8'h18; + 8'hae: d=8'hbe; + 8'haf: d=8'h1b; + 8'hb0: d=8'hfc; + 8'hb1: d=8'h56; + 8'hb2: d=8'h3e; + 8'hb3: d=8'h4b; + 8'hb4: d=8'hc6; + 8'hb5: d=8'hd2; + 8'hb6: d=8'h79; + 8'hb7: d=8'h20; + 8'hb8: d=8'h9a; + 8'hb9: d=8'hdb; + 8'hba: d=8'hc0; + 8'hbb: d=8'hfe; + 8'hbc: d=8'h78; + 8'hbd: d=8'hcd; + 8'hbe: d=8'h5a; + 8'hbf: d=8'hf4; + 8'hc0: d=8'h1f; + 8'hc1: d=8'hdd; + 8'hc2: d=8'ha8; + 8'hc3: d=8'h33; + 8'hc4: d=8'h88; + 8'hc5: d=8'h07; + 8'hc6: d=8'hc7; + 8'hc7: d=8'h31; + 8'hc8: d=8'hb1; + 8'hc9: d=8'h12; + 8'hca: d=8'h10; + 8'hcb: d=8'h59; + 8'hcc: d=8'h27; + 8'hcd: d=8'h80; + 8'hce: d=8'hec; + 8'hcf: d=8'h5f; + 8'hd0: d=8'h60; + 8'hd1: d=8'h51; + 8'hd2: d=8'h7f; + 8'hd3: d=8'ha9; + 8'hd4: d=8'h19; + 8'hd5: d=8'hb5; + 8'hd6: d=8'h4a; + 8'hd7: d=8'h0d; + 8'hd8: d=8'h2d; + 8'hd9: d=8'he5; + 8'hda: d=8'h7a; + 8'hdb: d=8'h9f; + 8'hdc: d=8'h93; + 8'hdd: d=8'hc9; + 8'hde: d=8'h9c; + 8'hdf: d=8'hef; + 8'he0: d=8'ha0; + 8'he1: d=8'he0; + 8'he2: d=8'h3b; + 8'he3: d=8'h4d; + 8'he4: d=8'hae; + 8'he5: d=8'h2a; + 8'he6: d=8'hf5; + 8'he7: d=8'hb0; + 8'he8: d=8'hc8; + 8'he9: d=8'heb; + 8'hea: d=8'hbb; + 8'heb: d=8'h3c; + 8'hec: d=8'h83; + 8'hed: d=8'h53; + 8'hee: d=8'h99; + 8'hef: d=8'h61; + 8'hf0: d=8'h17; + 8'hf1: d=8'h2b; + 8'hf2: d=8'h04; + 8'hf3: d=8'h7e; + 8'hf4: d=8'hba; + 8'hf5: d=8'h77; + 8'hf6: d=8'hd6; + 8'hf7: d=8'h26; + 8'hf8: d=8'he1; + 8'hf9: d=8'h69; + 8'hfa: d=8'h14; + 8'hfb: d=8'h63; + 8'hfc: d=8'h55; + 8'hfd: d=8'h21; + 8'hfe: d=8'h0c; + 8'hff: d=8'h7d; + endcase +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v new file mode 100644 index 000000000..ddc74b732 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Key Expand Block (for 128 bit keys) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_key_expand_128.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_key_expand_128.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_key_expand_128(clk, kld, key, wo_0, wo_1, wo_2, wo_3); +input clk; +input kld; +input [127:0] key; +output [31:0] wo_0, wo_1, wo_2, wo_3; +reg [31:0] w[3:0]; +wire [31:0] tmp_w; +wire [31:0] subword; +wire [31:0] rcon; + +assign wo_0 = w[0]; +assign wo_1 = w[1]; +assign wo_2 = w[2]; +assign wo_3 = w[3]; +always @(posedge clk) w[0] <= #1 kld ? key[127:096] : w[0]^subword^rcon; +always @(posedge clk) w[1] <= #1 kld ? key[095:064] : w[0]^w[1]^subword^rcon; +always @(posedge clk) w[2] <= #1 kld ? key[063:032] : w[0]^w[2]^w[1]^subword^rcon; +always @(posedge clk) w[3] <= #1 kld ? key[031:000] : w[0]^w[3]^w[2]^w[1]^subword^rcon; +assign tmp_w = w[3]; +aes_sbox u0( .a(tmp_w[23:16]), .d(subword[31:24])); +aes_sbox u1( .a(tmp_w[15:08]), .d(subword[23:16])); +aes_sbox u2( .a(tmp_w[07:00]), .d(subword[15:08])); +aes_sbox u3( .a(tmp_w[31:24]), .d(subword[07:00])); +aes_rcon r0( .clk(clk), .kld(kld), .out(rcon)); +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v new file mode 100644 index 000000000..c2c0a1242 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v @@ -0,0 +1,96 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES RCON Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_rcon.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_rcon.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_rcon(clk, kld, out); +input clk; +input kld; +output [31:0] out; +reg [31:0] out; +reg [3:0] rcnt; +wire [3:0] rcnt_next; + +always @(posedge clk) + if(kld) out <= #1 32'h01_00_00_00; + else out <= #1 frcon(rcnt_next); + +assign rcnt_next = rcnt + 4'h1; +always @(posedge clk) + if(kld) rcnt <= #1 4'h0; + else rcnt <= #1 rcnt_next; + +function [31:0] frcon; +input [3:0] i; +case(i) // synopsys parallel_case + 4'h0: frcon=32'h01_00_00_00; + 4'h1: frcon=32'h02_00_00_00; + 4'h2: frcon=32'h04_00_00_00; + 4'h3: frcon=32'h08_00_00_00; + 4'h4: frcon=32'h10_00_00_00; + 4'h5: frcon=32'h20_00_00_00; + 4'h6: frcon=32'h40_00_00_00; + 4'h7: frcon=32'h80_00_00_00; + 4'h8: frcon=32'h1b_00_00_00; + 4'h9: frcon=32'h36_00_00_00; + default: frcon=32'h00_00_00_00; +endcase +endfunction + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v new file mode 100644 index 000000000..e01d75ef8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v @@ -0,0 +1,329 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES SBOX (ROM) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_sbox.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_sbox.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_sbox(a,d); +input [7:0] a; +output [7:0] d; +reg [7:0] d; + +always @(a) + case(a) // synopsys full_case parallel_case + 8'h00: d=8'h63; + 8'h01: d=8'h7c; + 8'h02: d=8'h77; + 8'h03: d=8'h7b; + 8'h04: d=8'hf2; + 8'h05: d=8'h6b; + 8'h06: d=8'h6f; + 8'h07: d=8'hc5; + 8'h08: d=8'h30; + 8'h09: d=8'h01; + 8'h0a: d=8'h67; + 8'h0b: d=8'h2b; + 8'h0c: d=8'hfe; + 8'h0d: d=8'hd7; + 8'h0e: d=8'hab; + 8'h0f: d=8'h76; + 8'h10: d=8'hca; + 8'h11: d=8'h82; + 8'h12: d=8'hc9; + 8'h13: d=8'h7d; + 8'h14: d=8'hfa; + 8'h15: d=8'h59; + 8'h16: d=8'h47; + 8'h17: d=8'hf0; + 8'h18: d=8'had; + 8'h19: d=8'hd4; + 8'h1a: d=8'ha2; + 8'h1b: d=8'haf; + 8'h1c: d=8'h9c; + 8'h1d: d=8'ha4; + 8'h1e: d=8'h72; + 8'h1f: d=8'hc0; + 8'h20: d=8'hb7; + 8'h21: d=8'hfd; + 8'h22: d=8'h93; + 8'h23: d=8'h26; + 8'h24: d=8'h36; + 8'h25: d=8'h3f; + 8'h26: d=8'hf7; + 8'h27: d=8'hcc; + 8'h28: d=8'h34; + 8'h29: d=8'ha5; + 8'h2a: d=8'he5; + 8'h2b: d=8'hf1; + 8'h2c: d=8'h71; + 8'h2d: d=8'hd8; + 8'h2e: d=8'h31; + 8'h2f: d=8'h15; + 8'h30: d=8'h04; + 8'h31: d=8'hc7; + 8'h32: d=8'h23; + 8'h33: d=8'hc3; + 8'h34: d=8'h18; + 8'h35: d=8'h96; + 8'h36: d=8'h05; + 8'h37: d=8'h9a; + 8'h38: d=8'h07; + 8'h39: d=8'h12; + 8'h3a: d=8'h80; + 8'h3b: d=8'he2; + 8'h3c: d=8'heb; + 8'h3d: d=8'h27; + 8'h3e: d=8'hb2; + 8'h3f: d=8'h75; + 8'h40: d=8'h09; + 8'h41: d=8'h83; + 8'h42: d=8'h2c; + 8'h43: d=8'h1a; + 8'h44: d=8'h1b; + 8'h45: d=8'h6e; + 8'h46: d=8'h5a; + 8'h47: d=8'ha0; + 8'h48: d=8'h52; + 8'h49: d=8'h3b; + 8'h4a: d=8'hd6; + 8'h4b: d=8'hb3; + 8'h4c: d=8'h29; + 8'h4d: d=8'he3; + 8'h4e: d=8'h2f; + 8'h4f: d=8'h84; + 8'h50: d=8'h53; + 8'h51: d=8'hd1; + 8'h52: d=8'h00; + 8'h53: d=8'hed; + 8'h54: d=8'h20; + 8'h55: d=8'hfc; + 8'h56: d=8'hb1; + 8'h57: d=8'h5b; + 8'h58: d=8'h6a; + 8'h59: d=8'hcb; + 8'h5a: d=8'hbe; + 8'h5b: d=8'h39; + 8'h5c: d=8'h4a; + 8'h5d: d=8'h4c; + 8'h5e: d=8'h58; + 8'h5f: d=8'hcf; + 8'h60: d=8'hd0; + 8'h61: d=8'hef; + 8'h62: d=8'haa; + 8'h63: d=8'hfb; + 8'h64: d=8'h43; + 8'h65: d=8'h4d; + 8'h66: d=8'h33; + 8'h67: d=8'h85; + 8'h68: d=8'h45; + 8'h69: d=8'hf9; + 8'h6a: d=8'h02; + 8'h6b: d=8'h7f; + 8'h6c: d=8'h50; + 8'h6d: d=8'h3c; + 8'h6e: d=8'h9f; + 8'h6f: d=8'ha8; + 8'h70: d=8'h51; + 8'h71: d=8'ha3; + 8'h72: d=8'h40; + 8'h73: d=8'h8f; + 8'h74: d=8'h92; + 8'h75: d=8'h9d; + 8'h76: d=8'h38; + 8'h77: d=8'hf5; + 8'h78: d=8'hbc; + 8'h79: d=8'hb6; + 8'h7a: d=8'hda; + 8'h7b: d=8'h21; + 8'h7c: d=8'h10; + 8'h7d: d=8'hff; + 8'h7e: d=8'hf3; + 8'h7f: d=8'hd2; + 8'h80: d=8'hcd; + 8'h81: d=8'h0c; + 8'h82: d=8'h13; + 8'h83: d=8'hec; + 8'h84: d=8'h5f; + 8'h85: d=8'h97; + 8'h86: d=8'h44; + 8'h87: d=8'h17; + 8'h88: d=8'hc4; + 8'h89: d=8'ha7; + 8'h8a: d=8'h7e; + 8'h8b: d=8'h3d; + 8'h8c: d=8'h64; + 8'h8d: d=8'h5d; + 8'h8e: d=8'h19; + 8'h8f: d=8'h73; + 8'h90: d=8'h60; + 8'h91: d=8'h81; + 8'h92: d=8'h4f; + 8'h93: d=8'hdc; + 8'h94: d=8'h22; + 8'h95: d=8'h2a; + 8'h96: d=8'h90; + 8'h97: d=8'h88; + 8'h98: d=8'h46; + 8'h99: d=8'hee; + 8'h9a: d=8'hb8; + 8'h9b: d=8'h14; + 8'h9c: d=8'hde; + 8'h9d: d=8'h5e; + 8'h9e: d=8'h0b; + 8'h9f: d=8'hdb; + 8'ha0: d=8'he0; + 8'ha1: d=8'h32; + 8'ha2: d=8'h3a; + 8'ha3: d=8'h0a; + 8'ha4: d=8'h49; + 8'ha5: d=8'h06; + 8'ha6: d=8'h24; + 8'ha7: d=8'h5c; + 8'ha8: d=8'hc2; + 8'ha9: d=8'hd3; + 8'haa: d=8'hac; + 8'hab: d=8'h62; + 8'hac: d=8'h91; + 8'had: d=8'h95; + 8'hae: d=8'he4; + 8'haf: d=8'h79; + 8'hb0: d=8'he7; + 8'hb1: d=8'hc8; + 8'hb2: d=8'h37; + 8'hb3: d=8'h6d; + 8'hb4: d=8'h8d; + 8'hb5: d=8'hd5; + 8'hb6: d=8'h4e; + 8'hb7: d=8'ha9; + 8'hb8: d=8'h6c; + 8'hb9: d=8'h56; + 8'hba: d=8'hf4; + 8'hbb: d=8'hea; + 8'hbc: d=8'h65; + 8'hbd: d=8'h7a; + 8'hbe: d=8'hae; + 8'hbf: d=8'h08; + 8'hc0: d=8'hba; + 8'hc1: d=8'h78; + 8'hc2: d=8'h25; + 8'hc3: d=8'h2e; + 8'hc4: d=8'h1c; + 8'hc5: d=8'ha6; + 8'hc6: d=8'hb4; + 8'hc7: d=8'hc6; + 8'hc8: d=8'he8; + 8'hc9: d=8'hdd; + 8'hca: d=8'h74; + 8'hcb: d=8'h1f; + 8'hcc: d=8'h4b; + 8'hcd: d=8'hbd; + 8'hce: d=8'h8b; + 8'hcf: d=8'h8a; + 8'hd0: d=8'h70; + 8'hd1: d=8'h3e; + 8'hd2: d=8'hb5; + 8'hd3: d=8'h66; + 8'hd4: d=8'h48; + 8'hd5: d=8'h03; + 8'hd6: d=8'hf6; + 8'hd7: d=8'h0e; + 8'hd8: d=8'h61; + 8'hd9: d=8'h35; + 8'hda: d=8'h57; + 8'hdb: d=8'hb9; + 8'hdc: d=8'h86; + 8'hdd: d=8'hc1; + 8'hde: d=8'h1d; + 8'hdf: d=8'h9e; + 8'he0: d=8'he1; + 8'he1: d=8'hf8; + 8'he2: d=8'h98; + 8'he3: d=8'h11; + 8'he4: d=8'h69; + 8'he5: d=8'hd9; + 8'he6: d=8'h8e; + 8'he7: d=8'h94; + 8'he8: d=8'h9b; + 8'he9: d=8'h1e; + 8'hea: d=8'h87; + 8'heb: d=8'he9; + 8'hec: d=8'hce; + 8'hed: d=8'h55; + 8'hee: d=8'h28; + 8'hef: d=8'hdf; + 8'hf0: d=8'h8c; + 8'hf1: d=8'ha1; + 8'hf2: d=8'h89; + 8'hf3: d=8'h0d; + 8'hf4: d=8'hbf; + 8'hf5: d=8'he6; + 8'hf6: d=8'h42; + 8'hf7: d=8'h68; + 8'hf8: d=8'h41; + 8'hf9: d=8'h99; + 8'hfa: d=8'h2d; + 8'hfb: d=8'h0f; + 8'hfc: d=8'hb0; + 8'hfd: d=8'h54; + 8'hfe: d=8'hbb; + 8'hff: d=8'h16; + endcase + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v b/openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v new file mode 100644 index 000000000..ff9e265a8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/openfpga_flow/benchmarks/iwls2005/des/README.txt b/openfpga_flow/benchmarks/iwls2005/des/README.txt new file mode 100644 index 000000000..eedc74c9a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/README.txt @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// DES CORE //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + + +Triple DES Core +=============== +Attached is a Triple DES core implementation in verilog. It takes +three standard 56 bit keys and 64 bits of data as input and generates +a 64 bit encrypted/decrypted result. Two implementations are provided: + +1) Area Optimized (CBC Mode) + This is a sequential implementation and needs 48 cycles to complete + a full encryption/decryption cycle. + + +2) Performance Optimized (EBC Mode) + This is a pipelined implementation that has a 48 cycle pipeline + (plus 1 input and 1 output register). It can perform a complete + encryption/decryption every cycle. + +Performance +=========== +1) Area Optimized (CBC Mode) + 0.18u UMC ASIC process: 5.5K gates, > 160 Mhz + Spartan IIe 100-6 : 1450 LUTs (about 60%), 88MHz + +2) Performance Optimized (EBC Mode) + 0.18u UMC ASIC process: 55K Gates, 300MHz (19.2 Gbits/sec) + Virtex-II-1500-6: 79% utilization, 166Mhz (10.6 Gbits/sec) + + + +DES Core +======== +Attached is a DES core implementation in verilog. It takes a standard +56 bit key and 64 bits of data as input and generates a 64 bit +encrypted/decrypted result. Two implementations are provided: + +1) Area Optimized (CBC Mode) + This is a sequential implementation and needs 16 cycles to complete + a full encryption/decryption cycle. + + +2) Performance Optimized (EBC Mode) + This is a pipelined implementation that has a 16 cycle pipeline + (plus 1 input and 1 output register). It can perform a complete + encryption/decryption every cycle. + + +Performance +=========== +1) Area Optimized (CBC Mode) + 0.18u UMC ASIC process: >155Mhz 3K Gates + Altera APEX 20KE-1: 1106 lcells >27MHz + Altera FLEX 10K50E-1: 1283 lcells >43MHz + +2) Performance Optimized (EBC Mode) + 0.18u UMC ASIC process: >290Mhz 28K Gates + Altera APEX 20KE-1: 6688 lcells >53MHz + Altera FLEX 10K130E-1: 6485 lcells >76 Mhz + + + +Status +====== +31-Oct-2002 Added Triple DES +05-Oct-2001 Added decrypt input (Thanks to Mark Cynar for + providing the code) + Reorganized directory structure + Added Makefile + Cleaned up test benches +03-Feb-2001 Initial Release + + +Directory Structure +=================== +[core_root] + | + +-doc Documentation + | + +-bench--+ Test Bench + | +- verilog Verilog Sources + | +-vhdl VHDL Sources + | + +-rtl----+ Core RTL Sources + | +-verilog Verilog Sources + | +-vhdl VHDL Sources + | + +-sim----+ + | +-rtl_sim---+ Functional verification Directory + | | +-bin Makefiles/Run Scripts + | | +-run Working Directory + | | + | +-gate_sim--+ Functional & Timing Gate Level + | | Verification Directory + | +-bin Makefiles/Run Scripts + | +-run Working Directory + | + +-lint--+ Lint Directory Tree + | +-bin Makefiles/Run Scripts + | +-run Working Directory + | +-log Linter log & result files + | + +-syn---+ Synthesis Directory Tree + | +-bin Synthesis Scripts + | +-run Working Directory + | +-log Synthesis log files + | +-out Synthesis Output + + +About the Author +================ +To find out more about me (Rudolf Usselmann), please visit: +http://www.asics.ws diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v new file mode 100644 index 000000000..d8e30e28c --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v @@ -0,0 +1,95 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// DES //// +//// DES Top Level module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module des(desOut, desIn, key, decrypt, roundSel, clk); +output [63:0] desOut; +input [63:0] desIn; +input [55:0] key; +input decrypt; +input [3:0] roundSel; +input clk; + +wire [1:48] K_sub; +wire [1:64] IP, FP; +reg [1:32] L, R; +wire [1:32] Xin; +wire [1:32] Lout, Rout; +wire [1:32] out; + +assign Lout = (roundSel == 0) ? IP[33:64] : R; +assign Xin = (roundSel == 0) ? IP[01:32] : L; +assign Rout = Xin ^ out; +assign FP = { Rout, Lout}; + +crp u0( .P(out), .R(Lout), .K_sub(K_sub) ); + +always @(posedge clk) + L <= #1 Lout; + +always @(posedge clk) + R <= #1 Rout; + +// Select a subkey from key. +key_sel u1( + .K_sub( K_sub ), + .K( key ), + .roundSel( roundSel ), + .decrypt( decrypt ) + ); + +// Perform initial permutation +assign IP[1:64] = { desIn[06], desIn[14], desIn[22], desIn[30], desIn[38], desIn[46], + desIn[54], desIn[62], desIn[04], desIn[12], desIn[20], desIn[28], + desIn[36], desIn[44], desIn[52], desIn[60], desIn[02], desIn[10], + desIn[18], desIn[26], desIn[34], desIn[42], desIn[50], desIn[58], + desIn[00], desIn[08], desIn[16], desIn[24], desIn[32], desIn[40], + desIn[48], desIn[56], desIn[07], desIn[15], desIn[23], desIn[31], + desIn[39], desIn[47], desIn[55], desIn[63], desIn[05], desIn[13], + desIn[21], desIn[29], desIn[37], desIn[45], desIn[53], desIn[61], + desIn[03], desIn[11], desIn[19], desIn[27], desIn[35], desIn[43], + desIn[51], desIn[59], desIn[01], desIn[09], desIn[17], desIn[25], + desIn[33], desIn[41], desIn[49], desIn[57] }; + +// Perform final permutation +assign desOut = { FP[40], FP[08], FP[48], FP[16], FP[56], FP[24], FP[64], FP[32], + FP[39], FP[07], FP[47], FP[15], FP[55], FP[23], FP[63], FP[31], + FP[38], FP[06], FP[46], FP[14], FP[54], FP[22], FP[62], FP[30], + FP[37], FP[05], FP[45], FP[13], FP[53], FP[21], FP[61], FP[29], + FP[36], FP[04], FP[44], FP[12], FP[52], FP[20], FP[60], FP[28], + FP[35], FP[03], FP[43], FP[11], FP[51], FP[19], FP[59], FP[27], + FP[34], FP[02], FP[42], FP[10], FP[50], FP[18], FP[58], FP[26], + FP[33], FP[01], FP[41], FP[09], FP[49], FP[17], FP[57], FP[25] }; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v new file mode 100644 index 000000000..37004a5cb --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v @@ -0,0 +1,148 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// DES //// +//// DES Top Level module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module des3(desOut, desIn, key1, key2, key3, decrypt, roundSel, clk); +output [63:0] desOut; +input [63:0] desIn; +input [55:0] key1; +input [55:0] key2; +input [55:0] key3; +input decrypt; +input [5:0] roundSel; +input clk; + +wire [1:48] K_sub; +wire [1:64] IP, FP, tmp; +reg [1:64] FP_R; +reg [1:32] L, R; +wire [1:32] Xin; +wire [1:32] Lout; +wire [1:32] Rout; +wire [1:32] out; + +//assign Lout = (roundSel == 0) ? IP[33:64] : R; +//assign Xin = (roundSel == 0) ? IP[01:32] : L; + + +assign Lout = (roundSel == 0) ? IP[33:64] : + ( (roundSel == 16) ? FP_R[33:64] : + ( (roundSel == 32) ? FP_R[33:64] : + R )); + +assign Xin = (roundSel == 0) ? IP[01:32] : + ( (roundSel == 16) ? FP_R[01:32] : + ( (roundSel == 32) ? FP_R[01:32] : + L )); + + + +/* +always @(roundSel or IP or tmp or R or FP) + case(roundSel) + 6'h0: Lout = IP[33:64]; + 6'h10: Lout = FP[33:64]; + 6'h20: Lout = FP[33:64]; + default: Lout = R; + endcase + +always @(roundSel or IP or tmp or L or FP) + case(roundSel) + 6'h0: Xin = IP[01:32]; + 6'h10: Xin = FP[01:32]; + 6'h20: Xin = FP[01:32]; + default: Xin = L; + endcase +*/ + +always @(posedge clk) + FP_R <= #1 FP; + +assign Rout = Xin ^ out; +assign FP = { Rout, Lout}; + +crp u0( .P(out), .R(Lout), .K_sub(K_sub) ); + +always @(posedge clk) + L <= #1 Lout; + +always @(posedge clk) + R <= #1 Rout; + +// Select a subkey from key. +key_sel3 u1( + .K_sub( K_sub ), + .key1( key1 ), + .key2( key2 ), + .key3( key3 ), + .roundSel( roundSel ), + .decrypt( decrypt ) + ); + +assign tmp[1:64] = { desOut[06], desOut[14], desOut[22], desOut[30], desOut[38], desOut[46], + desOut[54], desOut[62], desOut[04], desOut[12], desOut[20], desOut[28], + desOut[36], desOut[44], desOut[52], desOut[60], desOut[02], desOut[10], + desOut[18], desOut[26], desOut[34], desOut[42], desOut[50], desOut[58], + desOut[00], desOut[08], desOut[16], desOut[24], desOut[32], desOut[40], + desOut[48], desOut[56], desOut[07], desOut[15], desOut[23], desOut[31], + desOut[39], desOut[47], desOut[55], desOut[63], desOut[05], desOut[13], + desOut[21], desOut[29], desOut[37], desOut[45], desOut[53], desOut[61], + desOut[03], desOut[11], desOut[19], desOut[27], desOut[35], desOut[43], + desOut[51], desOut[59], desOut[01], desOut[09], desOut[17], desOut[25], + desOut[33], desOut[41], desOut[49], desOut[57] }; + +// Perform initial permutation +assign IP[1:64] = { desIn[06], desIn[14], desIn[22], desIn[30], desIn[38], desIn[46], + desIn[54], desIn[62], desIn[04], desIn[12], desIn[20], desIn[28], + desIn[36], desIn[44], desIn[52], desIn[60], desIn[02], desIn[10], + desIn[18], desIn[26], desIn[34], desIn[42], desIn[50], desIn[58], + desIn[00], desIn[08], desIn[16], desIn[24], desIn[32], desIn[40], + desIn[48], desIn[56], desIn[07], desIn[15], desIn[23], desIn[31], + desIn[39], desIn[47], desIn[55], desIn[63], desIn[05], desIn[13], + desIn[21], desIn[29], desIn[37], desIn[45], desIn[53], desIn[61], + desIn[03], desIn[11], desIn[19], desIn[27], desIn[35], desIn[43], + desIn[51], desIn[59], desIn[01], desIn[09], desIn[17], desIn[25], + desIn[33], desIn[41], desIn[49], desIn[57] }; + +// Perform final permutation +assign desOut = { FP[40], FP[08], FP[48], FP[16], FP[56], FP[24], FP[64], FP[32], + FP[39], FP[07], FP[47], FP[15], FP[55], FP[23], FP[63], FP[31], + FP[38], FP[06], FP[46], FP[14], FP[54], FP[22], FP[62], FP[30], + FP[37], FP[05], FP[45], FP[13], FP[53], FP[21], FP[61], FP[29], + FP[36], FP[04], FP[44], FP[12], FP[52], FP[20], FP[60], FP[28], + FP[35], FP[03], FP[43], FP[11], FP[51], FP[19], FP[59], FP[27], + FP[34], FP[02], FP[42], FP[10], FP[50], FP[18], FP[58], FP[26], + FP[33], FP[01], FP[41], FP[09], FP[49], FP[17], FP[57], FP[25] }; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v new file mode 100644 index 000000000..8ee15e084 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v @@ -0,0 +1,464 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// KEY_SEL_Half //// +//// Select one of 16 sub-keys for round //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// Original: Rudolf Usselmann //// +//// //// +//// Modified : 2004/07/10 //// +//// Modified: Sakamoto YASUHIRO //// +//// Modified: for about Half slices decreased //// +//// (XILINX SPARTAN2 Number of SLICEs 546 to 258) //// +//// Web : http://hp.vector.co.jp/authors/VA014069 //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module key_sel(K_sub, K, roundSel, decrypt); +output [1:48] K_sub; +input [55:0] K; +input [3:0] roundSel; +input decrypt; + +reg [1:48] K_sub; +wire [1:48] K1, K2, K3, K4, K5, K6, K7, K8; + +//// Modified: for about Half slices decreased +wire [2:0] roundSelH; // ADD Sakamoto +wire decryptH; // ADD Sakamoto + +assign roundSelH[2:0] = roundSel[3] ? (~roundSel[2:0]) : roundSel[2:0]; +assign decryptH = decrypt ^ roundSel[3]; + +always @(K1 or K2 or K3 or K4 or K5 or K6 or K7 or K8 or roundSelH) + case (roundSelH) // synopsys full_case parallel_case + 0: K_sub = K1; + 1: K_sub = K2; + 2: K_sub = K3; + 3: K_sub = K4; + 4: K_sub = K5; + 5: K_sub = K6; + 6: K_sub = K7; + 7: K_sub = K8; + endcase + + +assign K8[1] = decryptH ? K[6] : K[24]; +assign K8[2] = decryptH ? K[27] : K[20]; +assign K8[3] = decryptH ? K[10] : K[3] ; +assign K8[4] = decryptH ? K[19] : K[12]; +assign K8[5] = decryptH ? K[54] : K[47]; +assign K8[6] = decryptH ? K[25] : K[18]; +assign K8[7] = decryptH ? K[11] : K[4] ; +assign K8[8] = decryptH ? K[47] : K[40]; +assign K8[9] = decryptH ? K[13] : K[6] ; +assign K8[10] = decryptH ? K[32] : K[25]; +assign K8[11] = decryptH ? K[55] : K[48]; +assign K8[12] = decryptH ? K[3] : K[53]; +assign K8[13] = decryptH ? K[12] : K[5] ; +assign K8[14] = decryptH ? K[41] : K[34]; +assign K8[15] = decryptH ? K[17] : K[10]; +assign K8[16] = decryptH ? K[18] : K[11]; +assign K8[17] = decryptH ? K[33] : K[26]; +assign K8[18] = decryptH ? K[46] : K[39]; +assign K8[19] = decryptH ? K[20] : K[13]; +assign K8[20] = decryptH ? K[39] : K[32]; +assign K8[21] = decryptH ? K[40] : K[33]; +assign K8[22] = decryptH ? K[48] : K[41]; +assign K8[23] = decryptH ? K[24] : K[17]; +assign K8[24] = decryptH ? K[4] : K[54]; +assign K8[25] = decryptH ? K[52] : K[45]; +assign K8[26] = decryptH ? K[15] : K[8] ; +assign K8[27] = decryptH ? K[9] : K[2] ; +assign K8[28] = decryptH ? K[51] : K[44]; +assign K8[29] = decryptH ? K[35] : K[28]; +assign K8[30] = decryptH ? K[36] : K[29]; +assign K8[31] = decryptH ? K[2] : K[50]; +assign K8[32] = decryptH ? K[45] : K[38]; +assign K8[33] = decryptH ? K[8] : K[1] ; +assign K8[34] = decryptH ? K[21] : K[14]; +assign K8[35] = decryptH ? K[23] : K[16]; +assign K8[36] = decryptH ? K[42] : K[35]; +assign K8[37] = decryptH ? K[14] : K[7] ; +assign K8[38] = decryptH ? K[49] : K[42]; +assign K8[39] = decryptH ? K[38] : K[31]; +assign K8[40] = decryptH ? K[43] : K[36]; +assign K8[41] = decryptH ? K[30] : K[23]; +assign K8[42] = decryptH ? K[22] : K[15]; +assign K8[43] = decryptH ? K[28] : K[21]; +assign K8[44] = decryptH ? K[0] : K[52]; +assign K8[45] = decryptH ? K[1] : K[49]; +assign K8[46] = decryptH ? K[44] : K[37]; +assign K8[47] = decryptH ? K[50] : K[43]; +assign K8[48] = decryptH ? K[16] : K[9] ; + +assign K7[1] = decryptH ? K[20] : K[10]; +assign K7[2] = decryptH ? K[41] : K[6] ; +assign K7[3] = decryptH ? K[24] : K[46]; +assign K7[4] = decryptH ? K[33] : K[55]; +assign K7[5] = decryptH ? K[11] : K[33]; +assign K7[6] = decryptH ? K[39] : K[4] ; +assign K7[7] = decryptH ? K[25] : K[47]; +assign K7[8] = decryptH ? K[4] : K[26]; +assign K7[9] = decryptH ? K[27] : K[17]; +assign K7[10] = decryptH ? K[46] : K[11]; +assign K7[11] = decryptH ? K[12] : K[34]; +assign K7[12] = decryptH ? K[17] : K[39]; +assign K7[13] = decryptH ? K[26] : K[48]; +assign K7[14] = decryptH ? K[55] : K[20]; +assign K7[15] = decryptH ? K[6] : K[53]; +assign K7[16] = decryptH ? K[32] : K[54]; +assign K7[17] = decryptH ? K[47] : K[12]; +assign K7[18] = decryptH ? K[3] : K[25]; +assign K7[19] = decryptH ? K[34] : K[24]; +assign K7[20] = decryptH ? K[53] : K[18]; +assign K7[21] = decryptH ? K[54] : K[19]; +assign K7[22] = decryptH ? K[5] : K[27]; +assign K7[23] = decryptH ? K[13] : K[3] ; +assign K7[24] = decryptH ? K[18] : K[40]; +assign K7[25] = decryptH ? K[7] : K[31]; +assign K7[26] = decryptH ? K[29] : K[49]; +assign K7[27] = decryptH ? K[23] : K[43]; +assign K7[28] = decryptH ? K[38] : K[30]; +assign K7[29] = decryptH ? K[49] : K[14]; +assign K7[30] = decryptH ? K[50] : K[15]; +assign K7[31] = decryptH ? K[16] : K[36]; +assign K7[32] = decryptH ? K[0] : K[51]; +assign K7[33] = decryptH ? K[22] : K[42]; +assign K7[34] = decryptH ? K[35] : K[0] ; +assign K7[35] = decryptH ? K[37] : K[2] ; +assign K7[36] = decryptH ? K[1] : K[21]; +assign K7[37] = decryptH ? K[28] : K[52]; +assign K7[38] = decryptH ? K[8] : K[28]; +assign K7[39] = decryptH ? K[52] : K[44]; +assign K7[40] = decryptH ? K[2] : K[22]; +assign K7[41] = decryptH ? K[44] : K[9] ; +assign K7[42] = decryptH ? K[36] : K[1] ; +assign K7[43] = decryptH ? K[42] : K[7] ; +assign K7[44] = decryptH ? K[14] : K[38]; +assign K7[45] = decryptH ? K[15] : K[35]; +assign K7[46] = decryptH ? K[31] : K[23]; +assign K7[47] = decryptH ? K[9] : K[29]; +assign K7[48] = decryptH ? K[30] : K[50]; + +assign K6[1] = decryptH ? K[34] : K[53]; +assign K6[2] = decryptH ? K[55] : K[17]; +assign K6[3] = decryptH ? K[13] : K[32]; +assign K6[4] = decryptH ? K[47] : K[41]; +assign K6[5] = decryptH ? K[25] : K[19]; +assign K6[6] = decryptH ? K[53] : K[47]; +assign K6[7] = decryptH ? K[39] : K[33]; +assign K6[8] = decryptH ? K[18] : K[12]; +assign K6[9] = decryptH ? K[41] : K[3] ; +assign K6[10] = decryptH ? K[3] : K[54]; +assign K6[11] = decryptH ? K[26] : K[20]; +assign K6[12] = decryptH ? K[6] : K[25]; +assign K6[13] = decryptH ? K[40] : K[34]; +assign K6[14] = decryptH ? K[12] : K[6] ; +assign K6[15] = decryptH ? K[20] : K[39]; +assign K6[16] = decryptH ? K[46] : K[40]; +assign K6[17] = decryptH ? K[4] : K[55]; +assign K6[18] = decryptH ? K[17] : K[11]; +assign K6[19] = decryptH ? K[48] : K[10]; +assign K6[20] = decryptH ? K[10] : K[4] ; +assign K6[21] = decryptH ? K[11] : K[5] ; +assign K6[22] = decryptH ? K[19] : K[13]; +assign K6[23] = decryptH ? K[27] : K[46]; +assign K6[24] = decryptH ? K[32] : K[26]; +assign K6[25] = decryptH ? K[21] : K[44]; +assign K6[26] = decryptH ? K[43] : K[35]; +assign K6[27] = decryptH ? K[37] : K[29]; +assign K6[28] = decryptH ? K[52] : K[16]; +assign K6[29] = decryptH ? K[8] : K[0] ; +assign K6[30] = decryptH ? K[9] : K[1] ; +assign K6[31] = decryptH ? K[30] : K[22]; +assign K6[32] = decryptH ? K[14] : K[37]; +assign K6[33] = decryptH ? K[36] : K[28]; +assign K6[34] = decryptH ? K[49] : K[45]; +assign K6[35] = decryptH ? K[51] : K[43]; +assign K6[36] = decryptH ? K[15] : K[7] ; +assign K6[37] = decryptH ? K[42] : K[38]; +assign K6[38] = decryptH ? K[22] : K[14]; +assign K6[39] = decryptH ? K[7] : K[30]; +assign K6[40] = decryptH ? K[16] : K[8] ; +assign K6[41] = decryptH ? K[31] : K[50]; +assign K6[42] = decryptH ? K[50] : K[42]; +assign K6[43] = decryptH ? K[1] : K[52]; +assign K6[44] = decryptH ? K[28] : K[51]; +assign K6[45] = decryptH ? K[29] : K[21]; +assign K6[46] = decryptH ? K[45] : K[9] ; +assign K6[47] = decryptH ? K[23] : K[15]; +assign K6[48] = decryptH ? K[44] : K[36]; + +assign K5[1] = decryptH ? K[48] : K[39]; +assign K5[2] = decryptH ? K[12] : K[3] ; +assign K5[3] = decryptH ? K[27] : K[18]; +assign K5[4] = decryptH ? K[4] : K[27]; +assign K5[5] = decryptH ? K[39] : K[5] ; +assign K5[6] = decryptH ? K[10] : K[33]; +assign K5[7] = decryptH ? K[53] : K[19]; +assign K5[8] = decryptH ? K[32] : K[55]; +assign K5[9] = decryptH ? K[55] : K[46]; +assign K5[10] = decryptH ? K[17] : K[40]; +assign K5[11] = decryptH ? K[40] : K[6] ; +assign K5[12] = decryptH ? K[20] : K[11]; +assign K5[13] = decryptH ? K[54] : K[20]; +assign K5[14] = decryptH ? K[26] : K[17]; +assign K5[15] = decryptH ? K[34] : K[25]; +assign K5[16] = decryptH ? K[3] : K[26]; +assign K5[17] = decryptH ? K[18] : K[41]; +assign K5[18] = decryptH ? K[6] : K[54]; +assign K5[19] = decryptH ? K[5] : K[53]; +assign K5[20] = decryptH ? K[24] : K[47]; +assign K5[21] = decryptH ? K[25] : K[48]; +assign K5[22] = decryptH ? K[33] : K[24]; +assign K5[23] = decryptH ? K[41] : K[32]; +assign K5[24] = decryptH ? K[46] : K[12]; +assign K5[25] = decryptH ? K[35] : K[30]; +assign K5[26] = decryptH ? K[2] : K[21]; +assign K5[27] = decryptH ? K[51] : K[15]; +assign K5[28] = decryptH ? K[7] : K[2] ; +assign K5[29] = decryptH ? K[22] : K[45]; +assign K5[30] = decryptH ? K[23] : K[42]; +assign K5[31] = decryptH ? K[44] : K[8] ; +assign K5[32] = decryptH ? K[28] : K[23]; +assign K5[33] = decryptH ? K[50] : K[14]; +assign K5[34] = decryptH ? K[8] : K[31]; +assign K5[35] = decryptH ? K[38] : K[29]; +assign K5[36] = decryptH ? K[29] : K[52]; +assign K5[37] = decryptH ? K[1] : K[51]; +assign K5[38] = decryptH ? K[36] : K[0] ; +assign K5[39] = decryptH ? K[21] : K[16]; +assign K5[40] = decryptH ? K[30] : K[49]; +assign K5[41] = decryptH ? K[45] : K[36]; +assign K5[42] = decryptH ? K[9] : K[28]; +assign K5[43] = decryptH ? K[15] : K[38]; +assign K5[44] = decryptH ? K[42] : K[37]; +assign K5[45] = decryptH ? K[43] : K[7] ; +assign K5[46] = decryptH ? K[0] : K[50]; +assign K5[47] = decryptH ? K[37] : K[1] ; +assign K5[48] = decryptH ? K[31] : K[22]; + +assign K4[1] = decryptH ? K[5] : K[25]; +assign K4[2] = decryptH ? K[26] : K[46]; +assign K4[3] = decryptH ? K[41] : K[4] ; +assign K4[4] = decryptH ? K[18] : K[13]; +assign K4[5] = decryptH ? K[53] : K[48]; +assign K4[6] = decryptH ? K[24] : K[19]; +assign K4[7] = decryptH ? K[10] : K[5] ; +assign K4[8] = decryptH ? K[46] : K[41]; +assign K4[9] = decryptH ? K[12] : K[32]; +assign K4[10] = decryptH ? K[6] : K[26]; +assign K4[11] = decryptH ? K[54] : K[17]; +assign K4[12] = decryptH ? K[34] : K[54]; +assign K4[13] = decryptH ? K[11] : K[6] ; +assign K4[14] = decryptH ? K[40] : K[3] ; +assign K4[15] = decryptH ? K[48] : K[11]; +assign K4[16] = decryptH ? K[17] : K[12]; +assign K4[17] = decryptH ? K[32] : K[27]; +assign K4[18] = decryptH ? K[20] : K[40]; +assign K4[19] = decryptH ? K[19] : K[39]; +assign K4[20] = decryptH ? K[13] : K[33]; +assign K4[21] = decryptH ? K[39] : K[34]; +assign K4[22] = decryptH ? K[47] : K[10]; +assign K4[23] = decryptH ? K[55] : K[18]; +assign K4[24] = decryptH ? K[3] : K[55]; +assign K4[25] = decryptH ? K[49] : K[16]; +assign K4[26] = decryptH ? K[16] : K[7] ; +assign K4[27] = decryptH ? K[38] : K[1] ; +assign K4[28] = decryptH ? K[21] : K[43]; +assign K4[29] = decryptH ? K[36] : K[31]; +assign K4[30] = decryptH ? K[37] : K[28]; +assign K4[31] = decryptH ? K[31] : K[49]; +assign K4[32] = decryptH ? K[42] : K[9] ; +assign K4[33] = decryptH ? K[9] : K[0] ; +assign K4[34] = decryptH ? K[22] : K[44]; +assign K4[35] = decryptH ? K[52] : K[15]; +assign K4[36] = decryptH ? K[43] : K[38]; +assign K4[37] = decryptH ? K[15] : K[37]; +assign K4[38] = decryptH ? K[50] : K[45]; +assign K4[39] = decryptH ? K[35] : K[2] ; +assign K4[40] = decryptH ? K[44] : K[35]; +assign K4[41] = decryptH ? K[0] : K[22]; +assign K4[42] = decryptH ? K[23] : K[14]; +assign K4[43] = decryptH ? K[29] : K[51]; +assign K4[44] = decryptH ? K[1] : K[23]; +assign K4[45] = decryptH ? K[2] : K[52]; +assign K4[46] = decryptH ? K[14] : K[36]; +assign K4[47] = decryptH ? K[51] : K[42]; +assign K4[48] = decryptH ? K[45] : K[8] ; + +assign K3[1] = decryptH ? K[19] : K[11]; +assign K3[2] = decryptH ? K[40] : K[32]; +assign K3[3] = decryptH ? K[55] : K[47]; +assign K3[4] = decryptH ? K[32] : K[24]; +assign K3[5] = decryptH ? K[10] : K[34]; +assign K3[6] = decryptH ? K[13] : K[5] ; +assign K3[7] = decryptH ? K[24] : K[48]; +assign K3[8] = decryptH ? K[3] : K[27]; +assign K3[9] = decryptH ? K[26] : K[18]; +assign K3[10] = decryptH ? K[20] : K[12]; +assign K3[11] = decryptH ? K[11] : K[3] ; +assign K3[12] = decryptH ? K[48] : K[40]; +assign K3[13] = decryptH ? K[25] : K[17]; +assign K3[14] = decryptH ? K[54] : K[46]; +assign K3[15] = decryptH ? K[5] : K[54]; +assign K3[16] = decryptH ? K[6] : K[55]; +assign K3[17] = decryptH ? K[46] : K[13]; +assign K3[18] = decryptH ? K[34] : K[26]; +assign K3[19] = decryptH ? K[33] : K[25]; +assign K3[20] = decryptH ? K[27] : K[19]; +assign K3[21] = decryptH ? K[53] : K[20]; +assign K3[22] = decryptH ? K[4] : K[53]; +assign K3[23] = decryptH ? K[12] : K[4] ; +assign K3[24] = decryptH ? K[17] : K[41]; +assign K3[25] = decryptH ? K[8] : K[2] ; +assign K3[26] = decryptH ? K[30] : K[52]; +assign K3[27] = decryptH ? K[52] : K[42]; +assign K3[28] = decryptH ? K[35] : K[29]; +assign K3[29] = decryptH ? K[50] : K[44]; +assign K3[30] = decryptH ? K[51] : K[14]; +assign K3[31] = decryptH ? K[45] : K[35]; +assign K3[32] = decryptH ? K[1] : K[50]; +assign K3[33] = decryptH ? K[23] : K[45]; +assign K3[34] = decryptH ? K[36] : K[30]; +assign K3[35] = decryptH ? K[7] : K[1] ; +assign K3[36] = decryptH ? K[2] : K[51]; +assign K3[37] = decryptH ? K[29] : K[23]; +assign K3[38] = decryptH ? K[9] : K[31]; +assign K3[39] = decryptH ? K[49] : K[43]; +assign K3[40] = decryptH ? K[31] : K[21]; +assign K3[41] = decryptH ? K[14] : K[8] ; +assign K3[42] = decryptH ? K[37] : K[0] ; +assign K3[43] = decryptH ? K[43] : K[37]; +assign K3[44] = decryptH ? K[15] : K[9] ; +assign K3[45] = decryptH ? K[16] : K[38]; +assign K3[46] = decryptH ? K[28] : K[22]; +assign K3[47] = decryptH ? K[38] : K[28]; +assign K3[48] = decryptH ? K[0] : K[49]; + +assign K2[1] = decryptH ? K[33] : K[54]; +assign K2[2] = decryptH ? K[54] : K[18]; +assign K2[3] = decryptH ? K[12] : K[33]; +assign K2[4] = decryptH ? K[46] : K[10]; +assign K2[5] = decryptH ? K[24] : K[20]; +assign K2[6] = decryptH ? K[27] : K[48]; +assign K2[7] = decryptH ? K[13] : K[34]; +assign K2[8] = decryptH ? K[17] : K[13]; +assign K2[9] = decryptH ? K[40] : K[4] ; +assign K2[10] = decryptH ? K[34] : K[55]; +assign K2[11] = decryptH ? K[25] : K[46]; +assign K2[12] = decryptH ? K[5] : K[26]; +assign K2[13] = decryptH ? K[39] : K[3] ; +assign K2[14] = decryptH ? K[11] : K[32]; +assign K2[15] = decryptH ? K[19] : K[40]; +assign K2[16] = decryptH ? K[20] : K[41]; +assign K2[17] = decryptH ? K[3] : K[24]; +assign K2[18] = decryptH ? K[48] : K[12]; +assign K2[19] = decryptH ? K[47] : K[11]; +assign K2[20] = decryptH ? K[41] : K[5] ; +assign K2[21] = decryptH ? K[10] : K[6] ; +assign K2[22] = decryptH ? K[18] : K[39]; +assign K2[23] = decryptH ? K[26] : K[47]; +assign K2[24] = decryptH ? K[6] : K[27]; +assign K2[25] = decryptH ? K[22] : K[43]; +assign K2[26] = decryptH ? K[44] : K[38]; +assign K2[27] = decryptH ? K[7] : K[28]; +assign K2[28] = decryptH ? K[49] : K[15]; +assign K2[29] = decryptH ? K[9] : K[30]; +assign K2[30] = decryptH ? K[38] : K[0] ; +assign K2[31] = decryptH ? K[0] : K[21]; +assign K2[32] = decryptH ? K[15] : K[36]; +assign K2[33] = decryptH ? K[37] : K[31]; +assign K2[34] = decryptH ? K[50] : K[16]; +assign K2[35] = decryptH ? K[21] : K[42]; +assign K2[36] = decryptH ? K[16] : K[37]; +assign K2[37] = decryptH ? K[43] : K[9] ; +assign K2[38] = decryptH ? K[23] : K[44]; +assign K2[39] = decryptH ? K[8] : K[29]; +assign K2[40] = decryptH ? K[45] : K[7] ; +assign K2[41] = decryptH ? K[28] : K[49]; +assign K2[42] = decryptH ? K[51] : K[45]; +assign K2[43] = decryptH ? K[2] : K[23]; +assign K2[44] = decryptH ? K[29] : K[50]; +assign K2[45] = decryptH ? K[30] : K[51]; +assign K2[46] = decryptH ? K[42] : K[8] ; +assign K2[47] = decryptH ? K[52] : K[14]; +assign K2[48] = decryptH ? K[14] : K[35]; + +assign K1[1] = decryptH ? K[40] : K[47]; +assign K1[2] = decryptH ? K[4] : K[11]; +assign K1[3] = decryptH ? K[19] : K[26]; +assign K1[4] = decryptH ? K[53] : K[3] ; +assign K1[5] = decryptH ? K[6] : K[13]; +assign K1[6] = decryptH ? K[34] : K[41]; +assign K1[7] = decryptH ? K[20] : K[27]; +assign K1[8] = decryptH ? K[24] : K[6] ; +assign K1[9] = decryptH ? K[47] : K[54]; +assign K1[10] = decryptH ? K[41] : K[48]; +assign K1[11] = decryptH ? K[32] : K[39]; +assign K1[12] = decryptH ? K[12] : K[19]; +assign K1[13] = decryptH ? K[46] : K[53]; +assign K1[14] = decryptH ? K[18] : K[25]; +assign K1[15] = decryptH ? K[26] : K[33]; +assign K1[16] = decryptH ? K[27] : K[34]; +assign K1[17] = decryptH ? K[10] : K[17]; +assign K1[18] = decryptH ? K[55] : K[5] ; +assign K1[19] = decryptH ? K[54] : K[4] ; +assign K1[20] = decryptH ? K[48] : K[55]; +assign K1[21] = decryptH ? K[17] : K[24]; +assign K1[22] = decryptH ? K[25] : K[32]; +assign K1[23] = decryptH ? K[33] : K[40]; +assign K1[24] = decryptH ? K[13] : K[20]; +assign K1[25] = decryptH ? K[29] : K[36]; +assign K1[26] = decryptH ? K[51] : K[31]; +assign K1[27] = decryptH ? K[14] : K[21]; +assign K1[28] = decryptH ? K[1] : K[8] ; +assign K1[29] = decryptH ? K[16] : K[23]; +assign K1[30] = decryptH ? K[45] : K[52]; +assign K1[31] = decryptH ? K[7] : K[14]; +assign K1[32] = decryptH ? K[22] : K[29]; +assign K1[33] = decryptH ? K[44] : K[51]; +assign K1[34] = decryptH ? K[2] : K[9] ; +assign K1[35] = decryptH ? K[28] : K[35]; +assign K1[36] = decryptH ? K[23] : K[30]; +assign K1[37] = decryptH ? K[50] : K[2] ; +assign K1[38] = decryptH ? K[30] : K[37]; +assign K1[39] = decryptH ? K[15] : K[22]; +assign K1[40] = decryptH ? K[52] : K[0] ; +assign K1[41] = decryptH ? K[35] : K[42]; +assign K1[42] = decryptH ? K[31] : K[38]; +assign K1[43] = decryptH ? K[9] : K[16]; +assign K1[44] = decryptH ? K[36] : K[43]; +assign K1[45] = decryptH ? K[37] : K[44]; +assign K1[46] = decryptH ? K[49] : K[1] ; +assign K1[47] = decryptH ? K[0] : K[7] ; +assign K1[48] = decryptH ? K[21] : K[28]; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v new file mode 100644 index 000000000..9f232c41d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v @@ -0,0 +1,865 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// KEY_SEL //// +//// Select one of 16 sub-keys for round //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module key_sel3(K_sub, key1, key2, key3, roundSel, decrypt); +output [1:48] K_sub; +input [55:0] key1, key2, key3; +input [5:0] roundSel; +input decrypt; + +wire decrypt_int; +reg [55:0] K; +reg [1:48] K_sub; +wire [1:48] K1, K2, K3, K4, K5, K6, K7, K8, K9; +wire [1:48] K10, K11, K12, K13, K14, K15, K16; + +always @(roundSel or decrypt or key1 or key2 or key3) + case ({decrypt, roundSel[5:4]}) // synopsys full_case parallel_case + 3'b0_00: K = key1; + 3'b0_01: K = key2; + 3'b0_10: K = key3; + 3'b1_00: K = key3; + 3'b1_01: K = key2; + 3'b1_10: K = key1; + endcase + +assign decrypt_int = (roundSel[5:4]==2'h1) ? !decrypt : decrypt; + +always @(K1 or K2 or K3 or K4 or K5 or K6 or K7 or K8 or K9 or K10 + or K11 or K12 or K13 or K14 or K15 or K16 or roundSel) + case(roundSel[3:0]) // synopsys full_case parallel_case + 0: K_sub = K1; + 1: K_sub = K2; + 2: K_sub = K3; + 3: K_sub = K4; + 4: K_sub = K5; + 5: K_sub = K6; + 6: K_sub = K7; + 7: K_sub = K8; + 8: K_sub = K9; + 9: K_sub = K10; + 10: K_sub = K11; + 11: K_sub = K12; + 12: K_sub = K13; + 13: K_sub = K14; + 14: K_sub = K15; + 15: K_sub = K16; + endcase + + +assign K16[1] = decrypt_int ? K[47] : K[40]; +assign K16[2] = decrypt_int ? K[11] : K[4]; +assign K16[3] = decrypt_int ? K[26] : K[19]; +assign K16[4] = decrypt_int ? K[3] : K[53]; +assign K16[5] = decrypt_int ? K[13] : K[6]; +assign K16[6] = decrypt_int ? K[41] : K[34]; +assign K16[7] = decrypt_int ? K[27] : K[20]; +assign K16[8] = decrypt_int ? K[6] : K[24]; +assign K16[9] = decrypt_int ? K[54] : K[47]; +assign K16[10] = decrypt_int ? K[48] : K[41]; +assign K16[11] = decrypt_int ? K[39] : K[32]; +assign K16[12] = decrypt_int ? K[19] : K[12]; +assign K16[13] = decrypt_int ? K[53] : K[46]; +assign K16[14] = decrypt_int ? K[25] : K[18]; +assign K16[15] = decrypt_int ? K[33] : K[26]; +assign K16[16] = decrypt_int ? K[34] : K[27]; +assign K16[17] = decrypt_int ? K[17] : K[10]; +assign K16[18] = decrypt_int ? K[5] : K[55]; +assign K16[19] = decrypt_int ? K[4] : K[54]; +assign K16[20] = decrypt_int ? K[55] : K[48]; +assign K16[21] = decrypt_int ? K[24] : K[17]; +assign K16[22] = decrypt_int ? K[32] : K[25]; +assign K16[23] = decrypt_int ? K[40] : K[33]; +assign K16[24] = decrypt_int ? K[20] : K[13]; +assign K16[25] = decrypt_int ? K[36] : K[29]; +assign K16[26] = decrypt_int ? K[31] : K[51]; +assign K16[27] = decrypt_int ? K[21] : K[14]; +assign K16[28] = decrypt_int ? K[8] : K[1]; +assign K16[29] = decrypt_int ? K[23] : K[16]; +assign K16[30] = decrypt_int ? K[52] : K[45]; +assign K16[31] = decrypt_int ? K[14] : K[7]; +assign K16[32] = decrypt_int ? K[29] : K[22]; +assign K16[33] = decrypt_int ? K[51] : K[44]; +assign K16[34] = decrypt_int ? K[9] : K[2]; +assign K16[35] = decrypt_int ? K[35] : K[28]; +assign K16[36] = decrypt_int ? K[30] : K[23]; +assign K16[37] = decrypt_int ? K[2] : K[50]; +assign K16[38] = decrypt_int ? K[37] : K[30]; +assign K16[39] = decrypt_int ? K[22] : K[15]; +assign K16[40] = decrypt_int ? K[0] : K[52]; +assign K16[41] = decrypt_int ? K[42] : K[35]; +assign K16[42] = decrypt_int ? K[38] : K[31]; +assign K16[43] = decrypt_int ? K[16] : K[9]; +assign K16[44] = decrypt_int ? K[43] : K[36]; +assign K16[45] = decrypt_int ? K[44] : K[37]; +assign K16[46] = decrypt_int ? K[1] : K[49]; +assign K16[47] = decrypt_int ? K[7] : K[0]; +assign K16[48] = decrypt_int ? K[28] : K[21]; + +assign K15[1] = decrypt_int ? K[54] : K[33]; +assign K15[2] = decrypt_int ? K[18] : K[54]; +assign K15[3] = decrypt_int ? K[33] : K[12]; +assign K15[4] = decrypt_int ? K[10] : K[46]; +assign K15[5] = decrypt_int ? K[20] : K[24]; +assign K15[6] = decrypt_int ? K[48] : K[27]; +assign K15[7] = decrypt_int ? K[34] : K[13]; +assign K15[8] = decrypt_int ? K[13] : K[17]; +assign K15[9] = decrypt_int ? K[4] : K[40]; +assign K15[10] = decrypt_int ? K[55] : K[34]; +assign K15[11] = decrypt_int ? K[46] : K[25]; +assign K15[12] = decrypt_int ? K[26] : K[5]; +assign K15[13] = decrypt_int ? K[3] : K[39]; +assign K15[14] = decrypt_int ? K[32] : K[11]; +assign K15[15] = decrypt_int ? K[40] : K[19]; +assign K15[16] = decrypt_int ? K[41] : K[20]; +assign K15[17] = decrypt_int ? K[24] : K[3]; +assign K15[18] = decrypt_int ? K[12] : K[48]; +assign K15[19] = decrypt_int ? K[11] : K[47]; +assign K15[20] = decrypt_int ? K[5] : K[41]; +assign K15[21] = decrypt_int ? K[6] : K[10]; +assign K15[22] = decrypt_int ? K[39] : K[18]; +assign K15[23] = decrypt_int ? K[47] : K[26]; +assign K15[24] = decrypt_int ? K[27] : K[6]; +assign K15[25] = decrypt_int ? K[43] : K[22]; +assign K15[26] = decrypt_int ? K[38] : K[44]; +assign K15[27] = decrypt_int ? K[28] : K[7]; +assign K15[28] = decrypt_int ? K[15] : K[49]; +assign K15[29] = decrypt_int ? K[30] : K[9]; +assign K15[30] = decrypt_int ? K[0] : K[38]; +assign K15[31] = decrypt_int ? K[21] : K[0]; +assign K15[32] = decrypt_int ? K[36] : K[15]; +assign K15[33] = decrypt_int ? K[31] : K[37]; +assign K15[34] = decrypt_int ? K[16] : K[50]; +assign K15[35] = decrypt_int ? K[42] : K[21]; +assign K15[36] = decrypt_int ? K[37] : K[16]; +assign K15[37] = decrypt_int ? K[9] : K[43]; +assign K15[38] = decrypt_int ? K[44] : K[23]; +assign K15[39] = decrypt_int ? K[29] : K[8]; +assign K15[40] = decrypt_int ? K[7] : K[45]; +assign K15[41] = decrypt_int ? K[49] : K[28]; +assign K15[42] = decrypt_int ? K[45] : K[51]; +assign K15[43] = decrypt_int ? K[23] : K[2]; +assign K15[44] = decrypt_int ? K[50] : K[29]; +assign K15[45] = decrypt_int ? K[51] : K[30]; +assign K15[46] = decrypt_int ? K[8] : K[42]; +assign K15[47] = decrypt_int ? K[14] : K[52]; +assign K15[48] = decrypt_int ? K[35] : K[14]; + +assign K14[1] = decrypt_int ? K[11] : K[19]; +assign K14[2] = decrypt_int ? K[32] : K[40]; +assign K14[3] = decrypt_int ? K[47] : K[55]; +assign K14[4] = decrypt_int ? K[24] : K[32]; +assign K14[5] = decrypt_int ? K[34] : K[10]; +assign K14[6] = decrypt_int ? K[5] : K[13]; +assign K14[7] = decrypt_int ? K[48] : K[24]; +assign K14[8] = decrypt_int ? K[27] : K[3]; +assign K14[9] = decrypt_int ? K[18] : K[26]; +assign K14[10] = decrypt_int ? K[12] : K[20]; +assign K14[11] = decrypt_int ? K[3] : K[11]; +assign K14[12] = decrypt_int ? K[40] : K[48]; +assign K14[13] = decrypt_int ? K[17] : K[25]; +assign K14[14] = decrypt_int ? K[46] : K[54]; +assign K14[15] = decrypt_int ? K[54] : K[5]; +assign K14[16] = decrypt_int ? K[55] : K[6]; +assign K14[17] = decrypt_int ? K[13] : K[46]; +assign K14[18] = decrypt_int ? K[26] : K[34]; +assign K14[19] = decrypt_int ? K[25] : K[33]; +assign K14[20] = decrypt_int ? K[19] : K[27]; +assign K14[21] = decrypt_int ? K[20] : K[53]; +assign K14[22] = decrypt_int ? K[53] : K[4]; +assign K14[23] = decrypt_int ? K[4] : K[12]; +assign K14[24] = decrypt_int ? K[41] : K[17]; +assign K14[25] = decrypt_int ? K[2] : K[8]; +assign K14[26] = decrypt_int ? K[52] : K[30]; +assign K14[27] = decrypt_int ? K[42] : K[52]; +assign K14[28] = decrypt_int ? K[29] : K[35]; +assign K14[29] = decrypt_int ? K[44] : K[50]; +assign K14[30] = decrypt_int ? K[14] : K[51]; +assign K14[31] = decrypt_int ? K[35] : K[45]; +assign K14[32] = decrypt_int ? K[50] : K[1]; +assign K14[33] = decrypt_int ? K[45] : K[23]; +assign K14[34] = decrypt_int ? K[30] : K[36]; +assign K14[35] = decrypt_int ? K[1] : K[7]; +assign K14[36] = decrypt_int ? K[51] : K[2]; +assign K14[37] = decrypt_int ? K[23] : K[29]; +assign K14[38] = decrypt_int ? K[31] : K[9]; +assign K14[39] = decrypt_int ? K[43] : K[49]; +assign K14[40] = decrypt_int ? K[21] : K[31]; +assign K14[41] = decrypt_int ? K[8] : K[14]; +assign K14[42] = decrypt_int ? K[0] : K[37]; +assign K14[43] = decrypt_int ? K[37] : K[43]; +assign K14[44] = decrypt_int ? K[9] : K[15]; +assign K14[45] = decrypt_int ? K[38] : K[16]; +assign K14[46] = decrypt_int ? K[22] : K[28]; +assign K14[47] = decrypt_int ? K[28] : K[38]; +assign K14[48] = decrypt_int ? K[49] : K[0]; + +assign K13[1] = decrypt_int ? K[25] : K[5]; +assign K13[2] = decrypt_int ? K[46] : K[26]; +assign K13[3] = decrypt_int ? K[4] : K[41]; +assign K13[4] = decrypt_int ? K[13] : K[18]; +assign K13[5] = decrypt_int ? K[48] : K[53]; +assign K13[6] = decrypt_int ? K[19] : K[24]; +assign K13[7] = decrypt_int ? K[5] : K[10]; +assign K13[8] = decrypt_int ? K[41] : K[46]; +assign K13[9] = decrypt_int ? K[32] : K[12]; +assign K13[10] = decrypt_int ? K[26] : K[6]; +assign K13[11] = decrypt_int ? K[17] : K[54]; +assign K13[12] = decrypt_int ? K[54] : K[34]; +assign K13[13] = decrypt_int ? K[6] : K[11]; +assign K13[14] = decrypt_int ? K[3] : K[40]; +assign K13[15] = decrypt_int ? K[11] : K[48]; +assign K13[16] = decrypt_int ? K[12] : K[17]; +assign K13[17] = decrypt_int ? K[27] : K[32]; +assign K13[18] = decrypt_int ? K[40] : K[20]; +assign K13[19] = decrypt_int ? K[39] : K[19]; +assign K13[20] = decrypt_int ? K[33] : K[13]; +assign K13[21] = decrypt_int ? K[34] : K[39]; +assign K13[22] = decrypt_int ? K[10] : K[47]; +assign K13[23] = decrypt_int ? K[18] : K[55]; +assign K13[24] = decrypt_int ? K[55] : K[3]; +assign K13[25] = decrypt_int ? K[16] : K[49]; +assign K13[26] = decrypt_int ? K[7] : K[16]; +assign K13[27] = decrypt_int ? K[1] : K[38]; +assign K13[28] = decrypt_int ? K[43] : K[21]; +assign K13[29] = decrypt_int ? K[31] : K[36]; +assign K13[30] = decrypt_int ? K[28] : K[37]; +assign K13[31] = decrypt_int ? K[49] : K[31]; +assign K13[32] = decrypt_int ? K[9] : K[42]; +assign K13[33] = decrypt_int ? K[0] : K[9]; +assign K13[34] = decrypt_int ? K[44] : K[22]; +assign K13[35] = decrypt_int ? K[15] : K[52]; +assign K13[36] = decrypt_int ? K[38] : K[43]; +assign K13[37] = decrypt_int ? K[37] : K[15]; +assign K13[38] = decrypt_int ? K[45] : K[50]; +assign K13[39] = decrypt_int ? K[2] : K[35]; +assign K13[40] = decrypt_int ? K[35] : K[44]; +assign K13[41] = decrypt_int ? K[22] : K[0]; +assign K13[42] = decrypt_int ? K[14] : K[23]; +assign K13[43] = decrypt_int ? K[51] : K[29]; +assign K13[44] = decrypt_int ? K[23] : K[1]; +assign K13[45] = decrypt_int ? K[52] : K[2]; +assign K13[46] = decrypt_int ? K[36] : K[14]; +assign K13[47] = decrypt_int ? K[42] : K[51]; +assign K13[48] = decrypt_int ? K[8] : K[45]; + +assign K12[1] = decrypt_int ? K[39] : K[48]; +assign K12[2] = decrypt_int ? K[3] : K[12]; +assign K12[3] = decrypt_int ? K[18] : K[27]; +assign K12[4] = decrypt_int ? K[27] : K[4]; +assign K12[5] = decrypt_int ? K[5] : K[39]; +assign K12[6] = decrypt_int ? K[33] : K[10]; +assign K12[7] = decrypt_int ? K[19] : K[53]; +assign K12[8] = decrypt_int ? K[55] : K[32]; +assign K12[9] = decrypt_int ? K[46] : K[55]; +assign K12[10] = decrypt_int ? K[40] : K[17]; +assign K12[11] = decrypt_int ? K[6] : K[40]; +assign K12[12] = decrypt_int ? K[11] : K[20]; +assign K12[13] = decrypt_int ? K[20] : K[54]; +assign K12[14] = decrypt_int ? K[17] : K[26]; +assign K12[15] = decrypt_int ? K[25] : K[34]; +assign K12[16] = decrypt_int ? K[26] : K[3]; +assign K12[17] = decrypt_int ? K[41] : K[18]; +assign K12[18] = decrypt_int ? K[54] : K[6]; +assign K12[19] = decrypt_int ? K[53] : K[5]; +assign K12[20] = decrypt_int ? K[47] : K[24]; +assign K12[21] = decrypt_int ? K[48] : K[25]; +assign K12[22] = decrypt_int ? K[24] : K[33]; +assign K12[23] = decrypt_int ? K[32] : K[41]; +assign K12[24] = decrypt_int ? K[12] : K[46]; +assign K12[25] = decrypt_int ? K[30] : K[35]; +assign K12[26] = decrypt_int ? K[21] : K[2]; +assign K12[27] = decrypt_int ? K[15] : K[51]; +assign K12[28] = decrypt_int ? K[2] : K[7]; +assign K12[29] = decrypt_int ? K[45] : K[22]; +assign K12[30] = decrypt_int ? K[42] : K[23]; +assign K12[31] = decrypt_int ? K[8] : K[44]; +assign K12[32] = decrypt_int ? K[23] : K[28]; +assign K12[33] = decrypt_int ? K[14] : K[50]; +assign K12[34] = decrypt_int ? K[31] : K[8]; +assign K12[35] = decrypt_int ? K[29] : K[38]; +assign K12[36] = decrypt_int ? K[52] : K[29]; +assign K12[37] = decrypt_int ? K[51] : K[1]; +assign K12[38] = decrypt_int ? K[0] : K[36]; +assign K12[39] = decrypt_int ? K[16] : K[21]; +assign K12[40] = decrypt_int ? K[49] : K[30]; +assign K12[41] = decrypt_int ? K[36] : K[45]; +assign K12[42] = decrypt_int ? K[28] : K[9]; +assign K12[43] = decrypt_int ? K[38] : K[15]; +assign K12[44] = decrypt_int ? K[37] : K[42]; +assign K12[45] = decrypt_int ? K[7] : K[43]; +assign K12[46] = decrypt_int ? K[50] : K[0]; +assign K12[47] = decrypt_int ? K[1] : K[37]; +assign K12[48] = decrypt_int ? K[22] : K[31]; + +assign K11[1] = decrypt_int ? K[53] : K[34]; +assign K11[2] = decrypt_int ? K[17] : K[55]; +assign K11[3] = decrypt_int ? K[32] : K[13]; +assign K11[4] = decrypt_int ? K[41] : K[47]; +assign K11[5] = decrypt_int ? K[19] : K[25]; +assign K11[6] = decrypt_int ? K[47] : K[53]; +assign K11[7] = decrypt_int ? K[33] : K[39]; +assign K11[8] = decrypt_int ? K[12] : K[18]; +assign K11[9] = decrypt_int ? K[3] : K[41]; +assign K11[10] = decrypt_int ? K[54] : K[3]; +assign K11[11] = decrypt_int ? K[20] : K[26]; +assign K11[12] = decrypt_int ? K[25] : K[6]; +assign K11[13] = decrypt_int ? K[34] : K[40]; +assign K11[14] = decrypt_int ? K[6] : K[12]; +assign K11[15] = decrypt_int ? K[39] : K[20]; +assign K11[16] = decrypt_int ? K[40] : K[46]; +assign K11[17] = decrypt_int ? K[55] : K[4]; +assign K11[18] = decrypt_int ? K[11] : K[17]; +assign K11[19] = decrypt_int ? K[10] : K[48]; +assign K11[20] = decrypt_int ? K[4] : K[10]; +assign K11[21] = decrypt_int ? K[5] : K[11]; +assign K11[22] = decrypt_int ? K[13] : K[19]; +assign K11[23] = decrypt_int ? K[46] : K[27]; +assign K11[24] = decrypt_int ? K[26] : K[32]; +assign K11[25] = decrypt_int ? K[44] : K[21]; +assign K11[26] = decrypt_int ? K[35] : K[43]; +assign K11[27] = decrypt_int ? K[29] : K[37]; +assign K11[28] = decrypt_int ? K[16] : K[52]; +assign K11[29] = decrypt_int ? K[0] : K[8]; +assign K11[30] = decrypt_int ? K[1] : K[9]; +assign K11[31] = decrypt_int ? K[22] : K[30]; +assign K11[32] = decrypt_int ? K[37] : K[14]; +assign K11[33] = decrypt_int ? K[28] : K[36]; +assign K11[34] = decrypt_int ? K[45] : K[49]; +assign K11[35] = decrypt_int ? K[43] : K[51]; +assign K11[36] = decrypt_int ? K[7] : K[15]; +assign K11[37] = decrypt_int ? K[38] : K[42]; +assign K11[38] = decrypt_int ? K[14] : K[22]; +assign K11[39] = decrypt_int ? K[30] : K[7]; +assign K11[40] = decrypt_int ? K[8] : K[16]; +assign K11[41] = decrypt_int ? K[50] : K[31]; +assign K11[42] = decrypt_int ? K[42] : K[50]; +assign K11[43] = decrypt_int ? K[52] : K[1]; +assign K11[44] = decrypt_int ? K[51] : K[28]; +assign K11[45] = decrypt_int ? K[21] : K[29]; +assign K11[46] = decrypt_int ? K[9] : K[45]; +assign K11[47] = decrypt_int ? K[15] : K[23]; +assign K11[48] = decrypt_int ? K[36] : K[44]; + +assign K10[1] = decrypt_int ? K[10] : K[20]; +assign K10[2] = decrypt_int ? K[6] : K[41]; +assign K10[3] = decrypt_int ? K[46] : K[24]; +assign K10[4] = decrypt_int ? K[55] : K[33]; +assign K10[5] = decrypt_int ? K[33] : K[11]; +assign K10[6] = decrypt_int ? K[4] : K[39]; +assign K10[7] = decrypt_int ? K[47] : K[25]; +assign K10[8] = decrypt_int ? K[26] : K[4]; +assign K10[9] = decrypt_int ? K[17] : K[27]; +assign K10[10] = decrypt_int ? K[11] : K[46]; +assign K10[11] = decrypt_int ? K[34] : K[12]; +assign K10[12] = decrypt_int ? K[39] : K[17]; +assign K10[13] = decrypt_int ? K[48] : K[26]; +assign K10[14] = decrypt_int ? K[20] : K[55]; +assign K10[15] = decrypt_int ? K[53] : K[6]; +assign K10[16] = decrypt_int ? K[54] : K[32]; +assign K10[17] = decrypt_int ? K[12] : K[47]; +assign K10[18] = decrypt_int ? K[25] : K[3]; +assign K10[19] = decrypt_int ? K[24] : K[34]; +assign K10[20] = decrypt_int ? K[18] : K[53]; +assign K10[21] = decrypt_int ? K[19] : K[54]; +assign K10[22] = decrypt_int ? K[27] : K[5]; +assign K10[23] = decrypt_int ? K[3] : K[13]; +assign K10[24] = decrypt_int ? K[40] : K[18]; +assign K10[25] = decrypt_int ? K[31] : K[7]; +assign K10[26] = decrypt_int ? K[49] : K[29]; +assign K10[27] = decrypt_int ? K[43] : K[23]; +assign K10[28] = decrypt_int ? K[30] : K[38]; +assign K10[29] = decrypt_int ? K[14] : K[49]; +assign K10[30] = decrypt_int ? K[15] : K[50]; +assign K10[31] = decrypt_int ? K[36] : K[16]; +assign K10[32] = decrypt_int ? K[51] : K[0]; +assign K10[33] = decrypt_int ? K[42] : K[22]; +assign K10[34] = decrypt_int ? K[0] : K[35]; +assign K10[35] = decrypt_int ? K[2] : K[37]; +assign K10[36] = decrypt_int ? K[21] : K[1]; +assign K10[37] = decrypt_int ? K[52] : K[28]; +assign K10[38] = decrypt_int ? K[28] : K[8]; +assign K10[39] = decrypt_int ? K[44] : K[52]; +assign K10[40] = decrypt_int ? K[22] : K[2]; +assign K10[41] = decrypt_int ? K[9] : K[44]; +assign K10[42] = decrypt_int ? K[1] : K[36]; +assign K10[43] = decrypt_int ? K[7] : K[42]; +assign K10[44] = decrypt_int ? K[38] : K[14]; +assign K10[45] = decrypt_int ? K[35] : K[15]; +assign K10[46] = decrypt_int ? K[23] : K[31]; +assign K10[47] = decrypt_int ? K[29] : K[9]; +assign K10[48] = decrypt_int ? K[50] : K[30]; + +assign K9[1] = decrypt_int ? K[24] : K[6]; +assign K9[2] = decrypt_int ? K[20] : K[27]; +assign K9[3] = decrypt_int ? K[3] : K[10]; +assign K9[4] = decrypt_int ? K[12] : K[19]; +assign K9[5] = decrypt_int ? K[47] : K[54]; +assign K9[6] = decrypt_int ? K[18] : K[25]; +assign K9[7] = decrypt_int ? K[4] : K[11]; +assign K9[8] = decrypt_int ? K[40] : K[47]; +assign K9[9] = decrypt_int ? K[6] : K[13]; +assign K9[10] = decrypt_int ? K[25] : K[32]; +assign K9[11] = decrypt_int ? K[48] : K[55]; +assign K9[12] = decrypt_int ? K[53] : K[3]; +assign K9[13] = decrypt_int ? K[5] : K[12]; +assign K9[14] = decrypt_int ? K[34] : K[41]; +assign K9[15] = decrypt_int ? K[10] : K[17]; +assign K9[16] = decrypt_int ? K[11] : K[18]; +assign K9[17] = decrypt_int ? K[26] : K[33]; +assign K9[18] = decrypt_int ? K[39] : K[46]; +assign K9[19] = decrypt_int ? K[13] : K[20]; +assign K9[20] = decrypt_int ? K[32] : K[39]; +assign K9[21] = decrypt_int ? K[33] : K[40]; +assign K9[22] = decrypt_int ? K[41] : K[48]; +assign K9[23] = decrypt_int ? K[17] : K[24]; +assign K9[24] = decrypt_int ? K[54] : K[4]; +assign K9[25] = decrypt_int ? K[45] : K[52]; +assign K9[26] = decrypt_int ? K[8] : K[15]; +assign K9[27] = decrypt_int ? K[2] : K[9]; +assign K9[28] = decrypt_int ? K[44] : K[51]; +assign K9[29] = decrypt_int ? K[28] : K[35]; +assign K9[30] = decrypt_int ? K[29] : K[36]; +assign K9[31] = decrypt_int ? K[50] : K[2]; +assign K9[32] = decrypt_int ? K[38] : K[45]; +assign K9[33] = decrypt_int ? K[1] : K[8]; +assign K9[34] = decrypt_int ? K[14] : K[21]; +assign K9[35] = decrypt_int ? K[16] : K[23]; +assign K9[36] = decrypt_int ? K[35] : K[42]; +assign K9[37] = decrypt_int ? K[7] : K[14]; +assign K9[38] = decrypt_int ? K[42] : K[49]; +assign K9[39] = decrypt_int ? K[31] : K[38]; +assign K9[40] = decrypt_int ? K[36] : K[43]; +assign K9[41] = decrypt_int ? K[23] : K[30]; +assign K9[42] = decrypt_int ? K[15] : K[22]; +assign K9[43] = decrypt_int ? K[21] : K[28]; +assign K9[44] = decrypt_int ? K[52] : K[0]; +assign K9[45] = decrypt_int ? K[49] : K[1]; +assign K9[46] = decrypt_int ? K[37] : K[44]; +assign K9[47] = decrypt_int ? K[43] : K[50]; +assign K9[48] = decrypt_int ? K[9] : K[16]; + +assign K8[1] = decrypt_int ? K[6] : K[24]; +assign K8[2] = decrypt_int ? K[27] : K[20]; +assign K8[3] = decrypt_int ? K[10] : K[3]; +assign K8[4] = decrypt_int ? K[19] : K[12]; +assign K8[5] = decrypt_int ? K[54] : K[47]; +assign K8[6] = decrypt_int ? K[25] : K[18]; +assign K8[7] = decrypt_int ? K[11] : K[4]; +assign K8[8] = decrypt_int ? K[47] : K[40]; +assign K8[9] = decrypt_int ? K[13] : K[6]; +assign K8[10] = decrypt_int ? K[32] : K[25]; +assign K8[11] = decrypt_int ? K[55] : K[48]; +assign K8[12] = decrypt_int ? K[3] : K[53]; +assign K8[13] = decrypt_int ? K[12] : K[5]; +assign K8[14] = decrypt_int ? K[41] : K[34]; +assign K8[15] = decrypt_int ? K[17] : K[10]; +assign K8[16] = decrypt_int ? K[18] : K[11]; +assign K8[17] = decrypt_int ? K[33] : K[26]; +assign K8[18] = decrypt_int ? K[46] : K[39]; +assign K8[19] = decrypt_int ? K[20] : K[13]; +assign K8[20] = decrypt_int ? K[39] : K[32]; +assign K8[21] = decrypt_int ? K[40] : K[33]; +assign K8[22] = decrypt_int ? K[48] : K[41]; +assign K8[23] = decrypt_int ? K[24] : K[17]; +assign K8[24] = decrypt_int ? K[4] : K[54]; +assign K8[25] = decrypt_int ? K[52] : K[45]; +assign K8[26] = decrypt_int ? K[15] : K[8]; +assign K8[27] = decrypt_int ? K[9] : K[2]; +assign K8[28] = decrypt_int ? K[51] : K[44]; +assign K8[29] = decrypt_int ? K[35] : K[28]; +assign K8[30] = decrypt_int ? K[36] : K[29]; +assign K8[31] = decrypt_int ? K[2] : K[50]; +assign K8[32] = decrypt_int ? K[45] : K[38]; +assign K8[33] = decrypt_int ? K[8] : K[1]; +assign K8[34] = decrypt_int ? K[21] : K[14]; +assign K8[35] = decrypt_int ? K[23] : K[16]; +assign K8[36] = decrypt_int ? K[42] : K[35]; +assign K8[37] = decrypt_int ? K[14] : K[7]; +assign K8[38] = decrypt_int ? K[49] : K[42]; +assign K8[39] = decrypt_int ? K[38] : K[31]; +assign K8[40] = decrypt_int ? K[43] : K[36]; +assign K8[41] = decrypt_int ? K[30] : K[23]; +assign K8[42] = decrypt_int ? K[22] : K[15]; +assign K8[43] = decrypt_int ? K[28] : K[21]; +assign K8[44] = decrypt_int ? K[0] : K[52]; +assign K8[45] = decrypt_int ? K[1] : K[49]; +assign K8[46] = decrypt_int ? K[44] : K[37]; +assign K8[47] = decrypt_int ? K[50] : K[43]; +assign K8[48] = decrypt_int ? K[16] : K[9]; + +assign K7[1] = decrypt_int ? K[20] : K[10]; +assign K7[2] = decrypt_int ? K[41] : K[6]; +assign K7[3] = decrypt_int ? K[24] : K[46]; +assign K7[4] = decrypt_int ? K[33] : K[55]; +assign K7[5] = decrypt_int ? K[11] : K[33]; +assign K7[6] = decrypt_int ? K[39] : K[4]; +assign K7[7] = decrypt_int ? K[25] : K[47]; +assign K7[8] = decrypt_int ? K[4] : K[26]; +assign K7[9] = decrypt_int ? K[27] : K[17]; +assign K7[10] = decrypt_int ? K[46] : K[11]; +assign K7[11] = decrypt_int ? K[12] : K[34]; +assign K7[12] = decrypt_int ? K[17] : K[39]; +assign K7[13] = decrypt_int ? K[26] : K[48]; +assign K7[14] = decrypt_int ? K[55] : K[20]; +assign K7[15] = decrypt_int ? K[6] : K[53]; +assign K7[16] = decrypt_int ? K[32] : K[54]; +assign K7[17] = decrypt_int ? K[47] : K[12]; +assign K7[18] = decrypt_int ? K[3] : K[25]; +assign K7[19] = decrypt_int ? K[34] : K[24]; +assign K7[20] = decrypt_int ? K[53] : K[18]; +assign K7[21] = decrypt_int ? K[54] : K[19]; +assign K7[22] = decrypt_int ? K[5] : K[27]; +assign K7[23] = decrypt_int ? K[13] : K[3]; +assign K7[24] = decrypt_int ? K[18] : K[40]; +assign K7[25] = decrypt_int ? K[7] : K[31]; +assign K7[26] = decrypt_int ? K[29] : K[49]; +assign K7[27] = decrypt_int ? K[23] : K[43]; +assign K7[28] = decrypt_int ? K[38] : K[30]; +assign K7[29] = decrypt_int ? K[49] : K[14]; +assign K7[30] = decrypt_int ? K[50] : K[15]; +assign K7[31] = decrypt_int ? K[16] : K[36]; +assign K7[32] = decrypt_int ? K[0] : K[51]; +assign K7[33] = decrypt_int ? K[22] : K[42]; +assign K7[34] = decrypt_int ? K[35] : K[0]; +assign K7[35] = decrypt_int ? K[37] : K[2]; +assign K7[36] = decrypt_int ? K[1] : K[21]; +assign K7[37] = decrypt_int ? K[28] : K[52]; +assign K7[38] = decrypt_int ? K[8] : K[28]; +assign K7[39] = decrypt_int ? K[52] : K[44]; +assign K7[40] = decrypt_int ? K[2] : K[22]; +assign K7[41] = decrypt_int ? K[44] : K[9]; +assign K7[42] = decrypt_int ? K[36] : K[1]; +assign K7[43] = decrypt_int ? K[42] : K[7]; +assign K7[44] = decrypt_int ? K[14] : K[38]; +assign K7[45] = decrypt_int ? K[15] : K[35]; +assign K7[46] = decrypt_int ? K[31] : K[23]; +assign K7[47] = decrypt_int ? K[9] : K[29]; +assign K7[48] = decrypt_int ? K[30] : K[50]; + +assign K6[1] = decrypt_int ? K[34] : K[53]; +assign K6[2] = decrypt_int ? K[55] : K[17]; +assign K6[3] = decrypt_int ? K[13] : K[32]; +assign K6[4] = decrypt_int ? K[47] : K[41]; +assign K6[5] = decrypt_int ? K[25] : K[19]; +assign K6[6] = decrypt_int ? K[53] : K[47]; +assign K6[7] = decrypt_int ? K[39] : K[33]; +assign K6[8] = decrypt_int ? K[18] : K[12]; +assign K6[9] = decrypt_int ? K[41] : K[3]; +assign K6[10] = decrypt_int ? K[3] : K[54]; +assign K6[11] = decrypt_int ? K[26] : K[20]; +assign K6[12] = decrypt_int ? K[6] : K[25]; +assign K6[13] = decrypt_int ? K[40] : K[34]; +assign K6[14] = decrypt_int ? K[12] : K[6]; +assign K6[15] = decrypt_int ? K[20] : K[39]; +assign K6[16] = decrypt_int ? K[46] : K[40]; +assign K6[17] = decrypt_int ? K[4] : K[55]; +assign K6[18] = decrypt_int ? K[17] : K[11]; +assign K6[19] = decrypt_int ? K[48] : K[10]; +assign K6[20] = decrypt_int ? K[10] : K[4]; +assign K6[21] = decrypt_int ? K[11] : K[5]; +assign K6[22] = decrypt_int ? K[19] : K[13]; +assign K6[23] = decrypt_int ? K[27] : K[46]; +assign K6[24] = decrypt_int ? K[32] : K[26]; +assign K6[25] = decrypt_int ? K[21] : K[44]; +assign K6[26] = decrypt_int ? K[43] : K[35]; +assign K6[27] = decrypt_int ? K[37] : K[29]; +assign K6[28] = decrypt_int ? K[52] : K[16]; +assign K6[29] = decrypt_int ? K[8] : K[0]; +assign K6[30] = decrypt_int ? K[9] : K[1]; +assign K6[31] = decrypt_int ? K[30] : K[22]; +assign K6[32] = decrypt_int ? K[14] : K[37]; +assign K6[33] = decrypt_int ? K[36] : K[28]; +assign K6[34] = decrypt_int ? K[49] : K[45]; +assign K6[35] = decrypt_int ? K[51] : K[43]; +assign K6[36] = decrypt_int ? K[15] : K[7]; +assign K6[37] = decrypt_int ? K[42] : K[38]; +assign K6[38] = decrypt_int ? K[22] : K[14]; +assign K6[39] = decrypt_int ? K[7] : K[30]; +assign K6[40] = decrypt_int ? K[16] : K[8]; +assign K6[41] = decrypt_int ? K[31] : K[50]; +assign K6[42] = decrypt_int ? K[50] : K[42]; +assign K6[43] = decrypt_int ? K[1] : K[52]; +assign K6[44] = decrypt_int ? K[28] : K[51]; +assign K6[45] = decrypt_int ? K[29] : K[21]; +assign K6[46] = decrypt_int ? K[45] : K[9]; +assign K6[47] = decrypt_int ? K[23] : K[15]; +assign K6[48] = decrypt_int ? K[44] : K[36]; + +assign K5[1] = decrypt_int ? K[48] : K[39]; +assign K5[2] = decrypt_int ? K[12] : K[3]; +assign K5[3] = decrypt_int ? K[27] : K[18]; +assign K5[4] = decrypt_int ? K[4] : K[27]; +assign K5[5] = decrypt_int ? K[39] : K[5]; +assign K5[6] = decrypt_int ? K[10] : K[33]; +assign K5[7] = decrypt_int ? K[53] : K[19]; +assign K5[8] = decrypt_int ? K[32] : K[55]; +assign K5[9] = decrypt_int ? K[55] : K[46]; +assign K5[10] = decrypt_int ? K[17] : K[40]; +assign K5[11] = decrypt_int ? K[40] : K[6]; +assign K5[12] = decrypt_int ? K[20] : K[11]; +assign K5[13] = decrypt_int ? K[54] : K[20]; +assign K5[14] = decrypt_int ? K[26] : K[17]; +assign K5[15] = decrypt_int ? K[34] : K[25]; +assign K5[16] = decrypt_int ? K[3] : K[26]; +assign K5[17] = decrypt_int ? K[18] : K[41]; +assign K5[18] = decrypt_int ? K[6] : K[54]; +assign K5[19] = decrypt_int ? K[5] : K[53]; +assign K5[20] = decrypt_int ? K[24] : K[47]; +assign K5[21] = decrypt_int ? K[25] : K[48]; +assign K5[22] = decrypt_int ? K[33] : K[24]; +assign K5[23] = decrypt_int ? K[41] : K[32]; +assign K5[24] = decrypt_int ? K[46] : K[12]; +assign K5[25] = decrypt_int ? K[35] : K[30]; +assign K5[26] = decrypt_int ? K[2] : K[21]; +assign K5[27] = decrypt_int ? K[51] : K[15]; +assign K5[28] = decrypt_int ? K[7] : K[2]; +assign K5[29] = decrypt_int ? K[22] : K[45]; +assign K5[30] = decrypt_int ? K[23] : K[42]; +assign K5[31] = decrypt_int ? K[44] : K[8]; +assign K5[32] = decrypt_int ? K[28] : K[23]; +assign K5[33] = decrypt_int ? K[50] : K[14]; +assign K5[34] = decrypt_int ? K[8] : K[31]; +assign K5[35] = decrypt_int ? K[38] : K[29]; +assign K5[36] = decrypt_int ? K[29] : K[52]; +assign K5[37] = decrypt_int ? K[1] : K[51]; +assign K5[38] = decrypt_int ? K[36] : K[0]; +assign K5[39] = decrypt_int ? K[21] : K[16]; +assign K5[40] = decrypt_int ? K[30] : K[49]; +assign K5[41] = decrypt_int ? K[45] : K[36]; +assign K5[42] = decrypt_int ? K[9] : K[28]; +assign K5[43] = decrypt_int ? K[15] : K[38]; +assign K5[44] = decrypt_int ? K[42] : K[37]; +assign K5[45] = decrypt_int ? K[43] : K[7]; +assign K5[46] = decrypt_int ? K[0] : K[50]; +assign K5[47] = decrypt_int ? K[37] : K[1]; +assign K5[48] = decrypt_int ? K[31] : K[22]; + +assign K4[1] = decrypt_int ? K[5] : K[25]; +assign K4[2] = decrypt_int ? K[26] : K[46]; +assign K4[3] = decrypt_int ? K[41] : K[4]; +assign K4[4] = decrypt_int ? K[18] : K[13]; +assign K4[5] = decrypt_int ? K[53] : K[48]; +assign K4[6] = decrypt_int ? K[24] : K[19]; +assign K4[7] = decrypt_int ? K[10] : K[5]; +assign K4[8] = decrypt_int ? K[46] : K[41]; +assign K4[9] = decrypt_int ? K[12] : K[32]; +assign K4[10] = decrypt_int ? K[6] : K[26]; +assign K4[11] = decrypt_int ? K[54] : K[17]; +assign K4[12] = decrypt_int ? K[34] : K[54]; +assign K4[13] = decrypt_int ? K[11] : K[6]; +assign K4[14] = decrypt_int ? K[40] : K[3]; +assign K4[15] = decrypt_int ? K[48] : K[11]; +assign K4[16] = decrypt_int ? K[17] : K[12]; +assign K4[17] = decrypt_int ? K[32] : K[27]; +assign K4[18] = decrypt_int ? K[20] : K[40]; +assign K4[19] = decrypt_int ? K[19] : K[39]; +assign K4[20] = decrypt_int ? K[13] : K[33]; +assign K4[21] = decrypt_int ? K[39] : K[34]; +assign K4[22] = decrypt_int ? K[47] : K[10]; +assign K4[23] = decrypt_int ? K[55] : K[18]; +assign K4[24] = decrypt_int ? K[3] : K[55]; +assign K4[25] = decrypt_int ? K[49] : K[16]; +assign K4[26] = decrypt_int ? K[16] : K[7]; +assign K4[27] = decrypt_int ? K[38] : K[1]; +assign K4[28] = decrypt_int ? K[21] : K[43]; +assign K4[29] = decrypt_int ? K[36] : K[31]; +assign K4[30] = decrypt_int ? K[37] : K[28]; +assign K4[31] = decrypt_int ? K[31] : K[49]; +assign K4[32] = decrypt_int ? K[42] : K[9]; +assign K4[33] = decrypt_int ? K[9] : K[0]; +assign K4[34] = decrypt_int ? K[22] : K[44]; +assign K4[35] = decrypt_int ? K[52] : K[15]; +assign K4[36] = decrypt_int ? K[43] : K[38]; +assign K4[37] = decrypt_int ? K[15] : K[37]; +assign K4[38] = decrypt_int ? K[50] : K[45]; +assign K4[39] = decrypt_int ? K[35] : K[2]; +assign K4[40] = decrypt_int ? K[44] : K[35]; +assign K4[41] = decrypt_int ? K[0] : K[22]; +assign K4[42] = decrypt_int ? K[23] : K[14]; +assign K4[43] = decrypt_int ? K[29] : K[51]; +assign K4[44] = decrypt_int ? K[1] : K[23]; +assign K4[45] = decrypt_int ? K[2] : K[52]; +assign K4[46] = decrypt_int ? K[14] : K[36]; +assign K4[47] = decrypt_int ? K[51] : K[42]; +assign K4[48] = decrypt_int ? K[45] : K[8]; + +assign K3[1] = decrypt_int ? K[19] : K[11]; +assign K3[2] = decrypt_int ? K[40] : K[32]; +assign K3[3] = decrypt_int ? K[55] : K[47]; +assign K3[4] = decrypt_int ? K[32] : K[24]; +assign K3[5] = decrypt_int ? K[10] : K[34]; +assign K3[6] = decrypt_int ? K[13] : K[5]; +assign K3[7] = decrypt_int ? K[24] : K[48]; +assign K3[8] = decrypt_int ? K[3] : K[27]; +assign K3[9] = decrypt_int ? K[26] : K[18]; +assign K3[10] = decrypt_int ? K[20] : K[12]; +assign K3[11] = decrypt_int ? K[11] : K[3]; +assign K3[12] = decrypt_int ? K[48] : K[40]; +assign K3[13] = decrypt_int ? K[25] : K[17]; +assign K3[14] = decrypt_int ? K[54] : K[46]; +assign K3[15] = decrypt_int ? K[5] : K[54]; +assign K3[16] = decrypt_int ? K[6] : K[55]; +assign K3[17] = decrypt_int ? K[46] : K[13]; +assign K3[18] = decrypt_int ? K[34] : K[26]; +assign K3[19] = decrypt_int ? K[33] : K[25]; +assign K3[20] = decrypt_int ? K[27] : K[19]; +assign K3[21] = decrypt_int ? K[53] : K[20]; +assign K3[22] = decrypt_int ? K[4] : K[53]; +assign K3[23] = decrypt_int ? K[12] : K[4]; +assign K3[24] = decrypt_int ? K[17] : K[41]; +assign K3[25] = decrypt_int ? K[8] : K[2]; +assign K3[26] = decrypt_int ? K[30] : K[52]; +assign K3[27] = decrypt_int ? K[52] : K[42]; +assign K3[28] = decrypt_int ? K[35] : K[29]; +assign K3[29] = decrypt_int ? K[50] : K[44]; +assign K3[30] = decrypt_int ? K[51] : K[14]; +assign K3[31] = decrypt_int ? K[45] : K[35]; +assign K3[32] = decrypt_int ? K[1] : K[50]; +assign K3[33] = decrypt_int ? K[23] : K[45]; +assign K3[34] = decrypt_int ? K[36] : K[30]; +assign K3[35] = decrypt_int ? K[7] : K[1]; +assign K3[36] = decrypt_int ? K[2] : K[51]; +assign K3[37] = decrypt_int ? K[29] : K[23]; +assign K3[38] = decrypt_int ? K[9] : K[31]; +assign K3[39] = decrypt_int ? K[49] : K[43]; +assign K3[40] = decrypt_int ? K[31] : K[21]; +assign K3[41] = decrypt_int ? K[14] : K[8]; +assign K3[42] = decrypt_int ? K[37] : K[0]; +assign K3[43] = decrypt_int ? K[43] : K[37]; +assign K3[44] = decrypt_int ? K[15] : K[9]; +assign K3[45] = decrypt_int ? K[16] : K[38]; +assign K3[46] = decrypt_int ? K[28] : K[22]; +assign K3[47] = decrypt_int ? K[38] : K[28]; +assign K3[48] = decrypt_int ? K[0] : K[49]; + +assign K2[1] = decrypt_int ? K[33] : K[54]; +assign K2[2] = decrypt_int ? K[54] : K[18]; +assign K2[3] = decrypt_int ? K[12] : K[33]; +assign K2[4] = decrypt_int ? K[46] : K[10]; +assign K2[5] = decrypt_int ? K[24] : K[20]; +assign K2[6] = decrypt_int ? K[27] : K[48]; +assign K2[7] = decrypt_int ? K[13] : K[34]; +assign K2[8] = decrypt_int ? K[17] : K[13]; +assign K2[9] = decrypt_int ? K[40] : K[4]; +assign K2[10] = decrypt_int ? K[34] : K[55]; +assign K2[11] = decrypt_int ? K[25] : K[46]; +assign K2[12] = decrypt_int ? K[5] : K[26]; +assign K2[13] = decrypt_int ? K[39] : K[3]; +assign K2[14] = decrypt_int ? K[11] : K[32]; +assign K2[15] = decrypt_int ? K[19] : K[40]; +assign K2[16] = decrypt_int ? K[20] : K[41]; +assign K2[17] = decrypt_int ? K[3] : K[24]; +assign K2[18] = decrypt_int ? K[48] : K[12]; +assign K2[19] = decrypt_int ? K[47] : K[11]; +assign K2[20] = decrypt_int ? K[41] : K[5]; +assign K2[21] = decrypt_int ? K[10] : K[6]; +assign K2[22] = decrypt_int ? K[18] : K[39]; +assign K2[23] = decrypt_int ? K[26] : K[47]; +assign K2[24] = decrypt_int ? K[6] : K[27]; +assign K2[25] = decrypt_int ? K[22] : K[43]; +assign K2[26] = decrypt_int ? K[44] : K[38]; +assign K2[27] = decrypt_int ? K[7] : K[28]; +assign K2[28] = decrypt_int ? K[49] : K[15]; +assign K2[29] = decrypt_int ? K[9] : K[30]; +assign K2[30] = decrypt_int ? K[38] : K[0]; +assign K2[31] = decrypt_int ? K[0] : K[21]; +assign K2[32] = decrypt_int ? K[15] : K[36]; +assign K2[33] = decrypt_int ? K[37] : K[31]; +assign K2[34] = decrypt_int ? K[50] : K[16]; +assign K2[35] = decrypt_int ? K[21] : K[42]; +assign K2[36] = decrypt_int ? K[16] : K[37]; +assign K2[37] = decrypt_int ? K[43] : K[9]; +assign K2[38] = decrypt_int ? K[23] : K[44]; +assign K2[39] = decrypt_int ? K[8] : K[29]; +assign K2[40] = decrypt_int ? K[45] : K[7]; +assign K2[41] = decrypt_int ? K[28] : K[49]; +assign K2[42] = decrypt_int ? K[51] : K[45]; +assign K2[43] = decrypt_int ? K[2] : K[23]; +assign K2[44] = decrypt_int ? K[29] : K[50]; +assign K2[45] = decrypt_int ? K[30] : K[51]; +assign K2[46] = decrypt_int ? K[42] : K[8]; +assign K2[47] = decrypt_int ? K[52] : K[14]; +assign K2[48] = decrypt_int ? K[14] : K[35]; + +assign K1[1] = decrypt_int ? K[40] : K[47]; +assign K1[2] = decrypt_int ? K[4] : K[11]; +assign K1[3] = decrypt_int ? K[19] : K[26]; +assign K1[4] = decrypt_int ? K[53] : K[3]; +assign K1[5] = decrypt_int ? K[6] : K[13]; +assign K1[6] = decrypt_int ? K[34] : K[41]; +assign K1[7] = decrypt_int ? K[20] : K[27]; +assign K1[8] = decrypt_int ? K[24] : K[6]; +assign K1[9] = decrypt_int ? K[47] : K[54]; +assign K1[10] = decrypt_int ? K[41] : K[48]; +assign K1[11] = decrypt_int ? K[32] : K[39]; +assign K1[12] = decrypt_int ? K[12] : K[19]; +assign K1[13] = decrypt_int ? K[46] : K[53]; +assign K1[14] = decrypt_int ? K[18] : K[25]; +assign K1[15] = decrypt_int ? K[26] : K[33]; +assign K1[16] = decrypt_int ? K[27] : K[34]; +assign K1[17] = decrypt_int ? K[10] : K[17]; +assign K1[18] = decrypt_int ? K[55] : K[5]; +assign K1[19] = decrypt_int ? K[54] : K[4]; +assign K1[20] = decrypt_int ? K[48] : K[55]; +assign K1[21] = decrypt_int ? K[17] : K[24]; +assign K1[22] = decrypt_int ? K[25] : K[32]; +assign K1[23] = decrypt_int ? K[33] : K[40]; +assign K1[24] = decrypt_int ? K[13] : K[20]; +assign K1[25] = decrypt_int ? K[29] : K[36]; +assign K1[26] = decrypt_int ? K[51] : K[31]; +assign K1[27] = decrypt_int ? K[14] : K[21]; +assign K1[28] = decrypt_int ? K[1] : K[8]; +assign K1[29] = decrypt_int ? K[16] : K[23]; +assign K1[30] = decrypt_int ? K[45] : K[52]; +assign K1[31] = decrypt_int ? K[7] : K[14]; +assign K1[32] = decrypt_int ? K[22] : K[29]; +assign K1[33] = decrypt_int ? K[44] : K[51]; +assign K1[34] = decrypt_int ? K[2] : K[9]; +assign K1[35] = decrypt_int ? K[28] : K[35]; +assign K1[36] = decrypt_int ? K[23] : K[30]; +assign K1[37] = decrypt_int ? K[50] : K[2]; +assign K1[38] = decrypt_int ? K[30] : K[37]; +assign K1[39] = decrypt_int ? K[15] : K[22]; +assign K1[40] = decrypt_int ? K[52] : K[0]; +assign K1[41] = decrypt_int ? K[35] : K[42]; +assign K1[42] = decrypt_int ? K[31] : K[38]; +assign K1[43] = decrypt_int ? K[9] : K[16]; +assign K1[44] = decrypt_int ? K[36] : K[43]; +assign K1[45] = decrypt_int ? K[37] : K[44]; +assign K1[46] = decrypt_int ? K[49] : K[1]; +assign K1[47] = decrypt_int ? K[0] : K[7]; +assign K1[48] = decrypt_int ? K[21] : K[28]; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/crp.v b/openfpga_flow/benchmarks/iwls2005/des/common/crp.v new file mode 100644 index 000000000..5985f2f1a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/crp.v @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// CRP //// +//// DES Crypt Module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module crp(P, R, K_sub); +output [1:32] P; +input [1:32] R; +input [1:48] K_sub; + +wire [1:48] E; +wire [1:48] X; +wire [1:32] S; + +assign E[1:48] = { R[32], R[1], R[2], R[3], R[4], R[5], R[4], R[5], + R[6], R[7], R[8], R[9], R[8], R[9], R[10], R[11], + R[12], R[13], R[12], R[13], R[14], R[15], R[16], + R[17], R[16], R[17], R[18], R[19], R[20], R[21], + R[20], R[21], R[22], R[23], R[24], R[25], R[24], + R[25], R[26], R[27], R[28], R[29], R[28], R[29], + R[30], R[31], R[32], R[1]}; + +assign X = E ^ K_sub; + +sbox1 u0( .addr(X[01:06]), .dout(S[01:04]) ); +sbox2 u1( .addr(X[07:12]), .dout(S[05:08]) ); +sbox3 u2( .addr(X[13:18]), .dout(S[09:12]) ); +sbox4 u3( .addr(X[19:24]), .dout(S[13:16]) ); +sbox5 u4( .addr(X[25:30]), .dout(S[17:20]) ); +sbox6 u5( .addr(X[31:36]), .dout(S[21:24]) ); +sbox7 u6( .addr(X[37:42]), .dout(S[25:28]) ); +sbox8 u7( .addr(X[43:48]), .dout(S[29:32]) ); + +assign P[1:32] = { S[16], S[7], S[20], S[21], S[29], S[12], S[28], + S[17], S[1], S[15], S[23], S[26], S[5], S[18], + S[31], S[10], S[2], S[8], S[24], S[14], S[32], + S[27], S[3], S[9], S[19], S[13], S[30], S[6], + S[22], S[11], S[4], S[25]}; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v new file mode 100644 index 000000000..76d5e22f6 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox1(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 14; + 1: dout = 4; + 2: dout = 13; + 3: dout = 1; + 4: dout = 2; + 5: dout = 15; + 6: dout = 11; + 7: dout = 8; + 8: dout = 3; + 9: dout = 10; + 10: dout = 6; + 11: dout = 12; + 12: dout = 5; + 13: dout = 9; + 14: dout = 0; + 15: dout = 7; + + 16: dout = 0; + 17: dout = 15; + 18: dout = 7; + 19: dout = 4; + 20: dout = 14; + 21: dout = 2; + 22: dout = 13; + 23: dout = 1; + 24: dout = 10; + 25: dout = 6; + 26: dout = 12; + 27: dout = 11; + 28: dout = 9; + 29: dout = 5; + 30: dout = 3; + 31: dout = 8; + + 32: dout = 4; + 33: dout = 1; + 34: dout = 14; + 35: dout = 8; + 36: dout = 13; + 37: dout = 6; + 38: dout = 2; + 39: dout = 11; + 40: dout = 15; + 41: dout = 12; + 42: dout = 9; + 43: dout = 7; + 44: dout = 3; + 45: dout = 10; + 46: dout = 5; + 47: dout = 0; + + 48: dout = 15; + 49: dout = 12; + 50: dout = 8; + 51: dout = 2; + 52: dout = 4; + 53: dout = 9; + 54: dout = 1; + 55: dout = 7; + 56: dout = 5; + 57: dout = 11; + 58: dout = 3; + 59: dout = 14; + 60: dout = 10; + 61: dout = 0; + 62: dout = 6; + 63: dout = 13; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v new file mode 100644 index 000000000..aa505f3a2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox2(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 15; + 1: dout = 1; + 2: dout = 8; + 3: dout = 14; + 4: dout = 6; + 5: dout = 11; + 6: dout = 3; + 7: dout = 4; + 8: dout = 9; + 9: dout = 7; + 10: dout = 2; + 11: dout = 13; + 12: dout = 12; + 13: dout = 0; + 14: dout = 5; + 15: dout = 10; + + 16: dout = 3; + 17: dout = 13; + 18: dout = 4; + 19: dout = 7; + 20: dout = 15; + 21: dout = 2; + 22: dout = 8; + 23: dout = 14; + 24: dout = 12; + 25: dout = 0; + 26: dout = 1; + 27: dout = 10; + 28: dout = 6; + 29: dout = 9; + 30: dout = 11; + 31: dout = 5; + + 32: dout = 0; + 33: dout = 14; + 34: dout = 7; + 35: dout = 11; + 36: dout = 10; + 37: dout = 4; + 38: dout = 13; + 39: dout = 1; + 40: dout = 5; + 41: dout = 8; + 42: dout = 12; + 43: dout = 6; + 44: dout = 9; + 45: dout = 3; + 46: dout = 2; + 47: dout = 15; + + 48: dout = 13; + 49: dout = 8; + 50: dout = 10; + 51: dout = 1; + 52: dout = 3; + 53: dout = 15; + 54: dout = 4; + 55: dout = 2; + 56: dout = 11; + 57: dout = 6; + 58: dout = 7; + 59: dout = 12; + 60: dout = 0; + 61: dout = 5; + 62: dout = 14; + 63: dout = 9; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v new file mode 100644 index 000000000..0c6cddf03 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox3(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 10; + 1: dout = 0; + 2: dout = 9; + 3: dout = 14; + 4: dout = 6; + 5: dout = 3; + 6: dout = 15; + 7: dout = 5; + 8: dout = 1; + 9: dout = 13; + 10: dout = 12; + 11: dout = 7; + 12: dout = 11; + 13: dout = 4; + 14: dout = 2; + 15: dout = 8; + + 16: dout = 13; + 17: dout = 7; + 18: dout = 0; + 19: dout = 9; + 20: dout = 3; + 21: dout = 4; + 22: dout = 6; + 23: dout = 10; + 24: dout = 2; + 25: dout = 8; + 26: dout = 5; + 27: dout = 14; + 28: dout = 12; + 29: dout = 11; + 30: dout = 15; + 31: dout = 1; + + 32: dout = 13; + 33: dout = 6; + 34: dout = 4; + 35: dout = 9; + 36: dout = 8; + 37: dout = 15; + 38: dout = 3; + 39: dout = 0; + 40: dout = 11; + 41: dout = 1; + 42: dout = 2; + 43: dout = 12; + 44: dout = 5; + 45: dout = 10; + 46: dout = 14; + 47: dout = 7; + + 48: dout = 1; + 49: dout = 10; + 50: dout = 13; + 51: dout = 0; + 52: dout = 6; + 53: dout = 9; + 54: dout = 8; + 55: dout = 7; + 56: dout = 4; + 57: dout = 15; + 58: dout = 14; + 59: dout = 3; + 60: dout = 11; + 61: dout = 5; + 62: dout = 2; + 63: dout = 12; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v new file mode 100644 index 000000000..ec531c1e8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox4(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 7; + 1: dout = 13; + 2: dout = 14; + 3: dout = 3; + 4: dout = 0; + 5: dout = 6; + 6: dout = 9; + 7: dout = 10; + 8: dout = 1; + 9: dout = 2; + 10: dout = 8; + 11: dout = 5; + 12: dout = 11; + 13: dout = 12; + 14: dout = 4; + 15: dout = 15; + + 16: dout = 13; + 17: dout = 8; + 18: dout = 11; + 19: dout = 5; + 20: dout = 6; + 21: dout = 15; + 22: dout = 0; + 23: dout = 3; + 24: dout = 4; + 25: dout = 7; + 26: dout = 2; + 27: dout = 12; + 28: dout = 1; + 29: dout = 10; + 30: dout = 14; + 31: dout = 9; + + 32: dout = 10; + 33: dout = 6; + 34: dout = 9; + 35: dout = 0; + 36: dout = 12; + 37: dout = 11; + 38: dout = 7; + 39: dout = 13; + 40: dout = 15; + 41: dout = 1; + 42: dout = 3; + 43: dout = 14; + 44: dout = 5; + 45: dout = 2; + 46: dout = 8; + 47: dout = 4; + + 48: dout = 3; + 49: dout = 15; + 50: dout = 0; + 51: dout = 6; + 52: dout = 10; + 53: dout = 1; + 54: dout = 13; + 55: dout = 8; + 56: dout = 9; + 57: dout = 4; + 58: dout = 5; + 59: dout = 11; + 60: dout = 12; + 61: dout = 7; + 62: dout = 2; + 63: dout = 14; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v new file mode 100644 index 000000000..f874c25cc --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox5(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 2; + 1: dout = 12; + 2: dout = 4; + 3: dout = 1; + 4: dout = 7; + 5: dout = 10; + 6: dout = 11; + 7: dout = 6; + 8: dout = 8; + 9: dout = 5; + 10: dout = 3; + 11: dout = 15; + 12: dout = 13; + 13: dout = 0; + 14: dout = 14; + 15: dout = 9; + + 16: dout = 14; + 17: dout = 11; + 18: dout = 2; + 19: dout = 12; + 20: dout = 4; + 21: dout = 7; + 22: dout = 13; + 23: dout = 1; + 24: dout = 5; + 25: dout = 0; + 26: dout = 15; + 27: dout = 10; + 28: dout = 3; + 29: dout = 9; + 30: dout = 8; + 31: dout = 6; + + 32: dout = 4; + 33: dout = 2; + 34: dout = 1; + 35: dout = 11; + 36: dout = 10; + 37: dout = 13; + 38: dout = 7; + 39: dout = 8; + 40: dout = 15; + 41: dout = 9; + 42: dout = 12; + 43: dout = 5; + 44: dout = 6; + 45: dout = 3; + 46: dout = 0; + 47: dout = 14; + + 48: dout = 11; + 49: dout = 8; + 50: dout = 12; + 51: dout = 7; + 52: dout = 1; + 53: dout = 14; + 54: dout = 2; + 55: dout = 13; + 56: dout = 6; + 57: dout = 15; + 58: dout = 0; + 59: dout = 9; + 60: dout = 10; + 61: dout = 4; + 62: dout = 5; + 63: dout = 3; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v new file mode 100644 index 000000000..58fc86af0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox6(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 12; + 1: dout = 1; + 2: dout = 10; + 3: dout = 15; + 4: dout = 9; + 5: dout = 2; + 6: dout = 6; + 7: dout = 8; + 8: dout = 0; + 9: dout = 13; + 10: dout = 3; + 11: dout = 4; + 12: dout = 14; + 13: dout = 7; + 14: dout = 5; + 15: dout = 11; + + 16: dout = 10; + 17: dout = 15; + 18: dout = 4; + 19: dout = 2; + 20: dout = 7; + 21: dout = 12; + 22: dout = 9; + 23: dout = 5; + 24: dout = 6; + 25: dout = 1; + 26: dout = 13; + 27: dout = 14; + 28: dout = 0; + 29: dout = 11; + 30: dout = 3; + 31: dout = 8; + + 32: dout = 9; + 33: dout = 14; + 34: dout = 15; + 35: dout = 5; + 36: dout = 2; + 37: dout = 8; + 38: dout = 12; + 39: dout = 3; + 40: dout = 7; + 41: dout = 0; + 42: dout = 4; + 43: dout = 10; + 44: dout = 1; + 45: dout = 13; + 46: dout = 11; + 47: dout = 6; + + 48: dout = 4; + 49: dout = 3; + 50: dout = 2; + 51: dout = 12; + 52: dout = 9; + 53: dout = 5; + 54: dout = 15; + 55: dout = 10; + 56: dout = 11; + 57: dout = 14; + 58: dout = 1; + 59: dout = 7; + 60: dout = 6; + 61: dout = 0; + 62: dout = 8; + 63: dout = 13; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v new file mode 100644 index 000000000..f27957e2f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox7(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 4; + 1: dout = 11; + 2: dout = 2; + 3: dout = 14; + 4: dout = 15; + 5: dout = 0; + 6: dout = 8; + 7: dout = 13; + 8: dout = 3; + 9: dout = 12; + 10: dout = 9; + 11: dout = 7; + 12: dout = 5; + 13: dout = 10; + 14: dout = 6; + 15: dout = 1; + + 16: dout = 13; + 17: dout = 0; + 18: dout = 11; + 19: dout = 7; + 20: dout = 4; + 21: dout = 9; + 22: dout = 1; + 23: dout = 10; + 24: dout = 14; + 25: dout = 3; + 26: dout = 5; + 27: dout = 12; + 28: dout = 2; + 29: dout = 15; + 30: dout = 8; + 31: dout = 6; + + 32: dout = 1; + 33: dout = 4; + 34: dout = 11; + 35: dout = 13; + 36: dout = 12; + 37: dout = 3; + 38: dout = 7; + 39: dout = 14; + 40: dout = 10; + 41: dout = 15; + 42: dout = 6; + 43: dout = 8; + 44: dout = 0; + 45: dout = 5; + 46: dout = 9; + 47: dout = 2; + + 48: dout = 6; + 49: dout = 11; + 50: dout = 13; + 51: dout = 8; + 52: dout = 1; + 53: dout = 4; + 54: dout = 10; + 55: dout = 7; + 56: dout = 9; + 57: dout = 5; + 58: dout = 0; + 59: dout = 15; + 60: dout = 14; + 61: dout = 2; + 62: dout = 3; + 63: dout = 12; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v b/openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v new file mode 100644 index 000000000..5ebad6388 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox8(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 13; + 1: dout = 2; + 2: dout = 8; + 3: dout = 4; + 4: dout = 6; + 5: dout = 15; + 6: dout = 11; + 7: dout = 1; + 8: dout = 10; + 9: dout = 9; + 10: dout = 3; + 11: dout = 14; + 12: dout = 5; + 13: dout = 0; + 14: dout = 12; + 15: dout = 7; + + 16: dout = 1; + 17: dout = 15; + 18: dout = 13; + 19: dout = 8; + 20: dout = 10; + 21: dout = 3; + 22: dout = 7; + 23: dout = 4; + 24: dout = 12; + 25: dout = 5; + 26: dout = 6; + 27: dout = 11; + 28: dout = 0; + 29: dout = 14; + 30: dout = 9; + 31: dout = 2; + + 32: dout = 7; + 33: dout = 11; + 34: dout = 4; + 35: dout = 1; + 36: dout = 9; + 37: dout = 12; + 38: dout = 14; + 39: dout = 2; + 40: dout = 0; + 41: dout = 6; + 42: dout = 10; + 43: dout = 13; + 44: dout = 15; + 45: dout = 3; + 46: dout = 5; + 47: dout = 8; + + 48: dout = 2; + 49: dout = 1; + 50: dout = 14; + 51: dout = 7; + 52: dout = 4; + 53: dout = 10; + 54: dout = 8; + 55: dout = 13; + 56: dout = 15; + 57: dout = 12; + 58: dout = 9; + 59: dout = 0; + 60: dout = 3; + 61: dout = 5; + 62: dout = 6; + 63: dout = 11; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v new file mode 100644 index 000000000..151f83863 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v @@ -0,0 +1,236 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// DES //// +//// DES Top Level module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module des(desOut, desIn, key, decrypt, clk); +output [63:0] desOut; +input [63:0] desIn; +input [55:0] key; +input decrypt; +input clk; + +wire [1:64] IP, FP; +reg [63:0] desIn_r; +reg [55:0] key_r; +reg [63:0] desOut; +reg [1:32] L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15; +reg [1:32] R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15; +wire [1:32] out0, out1, out2, out3, out4, out5, out6, out7, out8, out9, out10, out11, out12, out13, out14, out15; +wire [1:48] K1, K2, K3, K4, K5, K6, K7, K8, K9; +wire [1:48] K10, K11, K12, K13, K14, K15, K16; + +// Register the 56 bit key +always @(posedge clk) + key_r <= #1 key; + +// Register the 64 bit input +always @(posedge clk) + desIn_r <= #1 desIn; + +// XOR 32 bit out15 with 32 bit L14 ( FP 1:32 ) +// then concatinate the 32 bit R14 value ( FP 33:64 ) +// This value ( FP 1:64 ) is then registered by the desOut[63:0] register +assign FP = { (out15 ^ L14), R14}; + +// Key schedule provides a linear means of intermixing the 56 bit key to form a +// different 48 bit key for each of the 16 bit rounds +key_sel uk( + .clk( clk ), + .K( key_r ), + .decrypt( decrypt ), + .K1( K1 ), + .K2( K2 ), + .K3( K3 ), + .K4( K4 ), + .K5( K5 ), + .K6( K6 ), + .K7( K7 ), + .K8( K8 ), + .K9( K9 ), + .K10( K10 ), + .K11( K11 ), + .K12( K12 ), + .K13( K13 ), + .K14( K14 ), + .K15( K15 ), + .K16( K16 ) + ); + +// 16 CRP blocks +crp u0( .P(out0), .R(IP[33:64]), .K_sub(K1) ); +crp u1( .P(out1), .R(R0), .K_sub(K2) ); +crp u2( .P(out2), .R(R1), .K_sub(K3) ); +crp u3( .P(out3), .R(R2), .K_sub(K4) ); +crp u4( .P(out4), .R(R3), .K_sub(K5) ); +crp u5( .P(out5), .R(R4), .K_sub(K6) ); +crp u6( .P(out6), .R(R5), .K_sub(K7) ); +crp u7( .P(out7), .R(R6), .K_sub(K8) ); +crp u8( .P(out8), .R(R7), .K_sub(K9) ); +crp u9( .P(out9), .R(R8), .K_sub(K10) ); +crp u10( .P(out10), .R(R9), .K_sub(K11) ); +crp u11( .P(out11), .R(R10), .K_sub(K12) ); +crp u12( .P(out12), .R(R11), .K_sub(K13) ); +crp u13( .P(out13), .R(R12), .K_sub(K14) ); +crp u14( .P(out14), .R(R13), .K_sub(K15) ); +crp u15( .P(out15), .R(R14), .K_sub(K16) ); + +// 32 bit L0 get upper 32 bits of IP +always @(posedge clk) + L0 <= #1 IP[33:64]; + +// 32 bit R0 gets lower 32 bits of IP XOR'd with 32 bit out0 +always @(posedge clk) + R0 <= #1 IP[01:32] ^ out0; + +// 32 bit L1 gets 32 bit R0 +always @(posedge clk) + L1 <= #1 R0; + +// 32 bit R1 gets 32 bit L0 XOR'd with 32 bit out1 +always @(posedge clk) + R1 <= #1 L0 ^ out1; + +// 32 bit L2 gets 32 bit R1 +always @(posedge clk) + L2 <= #1 R1; + +// 32 bit R2 gets 32 bit L1 XOR'd with 32 bit out2 +always @(posedge clk) + R2 <= #1 L1 ^ out2; + +always @(posedge clk) + L3 <= #1 R2; + +always @(posedge clk) + R3 <= #1 L2 ^ out3; + +always @(posedge clk) + L4 <= #1 R3; + +always @(posedge clk) + R4 <= #1 L3 ^ out4; + +always @(posedge clk) + L5 <= #1 R4; + +always @(posedge clk) + R5 <= #1 L4 ^ out5; + +always @(posedge clk) + L6 <= #1 R5; + +always @(posedge clk) + R6 <= #1 L5 ^ out6; + +always @(posedge clk) + L7 <= #1 R6; + +always @(posedge clk) + R7 <= #1 L6 ^ out7; + +always @(posedge clk) + L8 <= #1 R7; + +always @(posedge clk) + R8 <= #1 L7 ^ out8; + +always @(posedge clk) + L9 <= #1 R8; + +always @(posedge clk) + R9 <= #1 L8 ^ out9; + +always @(posedge clk) + L10 <= #1 R9; + +always @(posedge clk) + R10 <= #1 L9 ^ out10; + +always @(posedge clk) + L11 <= #1 R10; + +always @(posedge clk) + R11 <= #1 L10 ^ out11; + +always @(posedge clk) + L12 <= #1 R11; + +always @(posedge clk) + R12 <= #1 L11 ^ out12; + +always @(posedge clk) + L13 <= #1 R12; + +always @(posedge clk) + R13 <= #1 L12 ^ out13; + +always @(posedge clk) + L14 <= #1 R13; + +always @(posedge clk) + R14 <= #1 L13 ^ out14; + +// 32 bit L15 gets 32 bit R14 +always @(posedge clk) + L15 <= #1 R14; + +// 32 bit R15 gets 32 bit L14 XOR'd with 32 bit out15 +always @(posedge clk) + R15 <= #1 L14 ^ out15; + +// Perform the initial permutationi with the registerd desIn +assign IP[1:64] = { desIn_r[06], desIn_r[14], desIn_r[22], desIn_r[30], desIn_r[38], desIn_r[46], + desIn_r[54], desIn_r[62], desIn_r[04], desIn_r[12], desIn_r[20], desIn_r[28], + desIn_r[36], desIn_r[44], desIn_r[52], desIn_r[60], desIn_r[02], desIn_r[10], + desIn_r[18], desIn_r[26], desIn_r[34], desIn_r[42], desIn_r[50], desIn_r[58], + desIn_r[00], desIn_r[08], desIn_r[16], desIn_r[24], desIn_r[32], desIn_r[40], + desIn_r[48], desIn_r[56], desIn_r[07], desIn_r[15], desIn_r[23], desIn_r[31], + desIn_r[39], desIn_r[47], desIn_r[55], desIn_r[63], desIn_r[05], desIn_r[13], + desIn_r[21], desIn_r[29], desIn_r[37], desIn_r[45], desIn_r[53], desIn_r[61], + desIn_r[03], desIn_r[11], desIn_r[19], desIn_r[27], desIn_r[35], desIn_r[43], + desIn_r[51], desIn_r[59], desIn_r[01], desIn_r[09], desIn_r[17], desIn_r[25], + desIn_r[33], desIn_r[41], desIn_r[49], desIn_r[57] }; + +// Perform the final permutation +always @(posedge clk) + desOut <= #1 { FP[40], FP[08], FP[48], FP[16], FP[56], FP[24], FP[64], FP[32], + FP[39], FP[07], FP[47], FP[15], FP[55], FP[23], FP[63], FP[31], + FP[38], FP[06], FP[46], FP[14], FP[54], FP[22], FP[62], FP[30], + FP[37], FP[05], FP[45], FP[13], FP[53], FP[21], FP[61], FP[29], + FP[36], FP[04], FP[44], FP[12], FP[52], FP[20], FP[60], FP[28], + FP[35], FP[03], FP[43], FP[11], FP[51], FP[19], FP[59], FP[27], + FP[34], FP[02], FP[42], FP[10], FP[50], FP[18], FP[58], FP[26], + FP[33], FP[01], FP[41], FP[09], FP[49], FP[17], FP[57], FP[25] }; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v new file mode 100644 index 000000000..d9a4e7f4f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Tripple DES //// +//// Tripple DES Top Level module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module des3(desOut, desIn, key1, key2, key3, decrypt, clk); +output [63:0] desOut; +input [63:0] desIn; +input [55:0] key1; +input [55:0] key2; +input [55:0] key3; +input decrypt; +input clk; + +wire [55:0] key_a; +wire [55:0] key_b; +wire [55:0] key_c; +wire [63:0] stage1_out, stage2_out; +reg [55:0] key_b_r [16:0]; +reg [55:0] key_c_r [33:0]; +integer i; + +assign key_a = decrypt ? key3 : key1; +assign key_b = key2; +assign key_c = decrypt ? key1 : key3; + +always @(posedge clk) + key_b_r[0] <= #1 key_b; + +always @(posedge clk) + for(i=0;i<16;i=i+1) + key_b_r[i+1] <= #1 key_b_r[i]; + + +always @(posedge clk) + key_c_r[0] <= #1 key_c; + +always @(posedge clk) + for(i=0;i<33;i=i+1) + key_c_r[i+1] <= #1 key_c_r[i]; + +des u0( .desOut(stage1_out), .desIn(desIn), .key(key_a), .decrypt(decrypt), .clk(clk) ); + +des u1( .desOut(stage2_out), .desIn(stage1_out), .key(key_b_r[16]), .decrypt(!decrypt), .clk(clk) ); + +des u2( .desOut(desOut), .desIn(stage2_out), .key(key_c_r[33]), .decrypt(decrypt), .clk(clk) ); + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v new file mode 100644 index 000000000..c5598d61d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v @@ -0,0 +1,852 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// KEY_SEL //// +//// Generate 16 pipelined sub-keys //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +module key_sel(clk, K, decrypt, K1, K2, K3, K4, K5, K6, K7, K8, K9, + K10, K11, K12, K13, K14, K15, K16); +input clk; +input [55:0] K; +input decrypt; +output [1:48] K1, K2, K3, K4, K5, K6, K7, K8, K9; +output [1:48] K10, K11, K12, K13, K14, K15, K16; + +wire [1:48] K1, K2, K3, K4, K5, K6, K7, K8, K9; +wire [1:48] K10, K11, K12, K13, K14, K15, K16; +reg [55:0] K_r0, K_r1, K_r2, K_r3, K_r4, K_r5, K_r6, K_r7; +reg [55:0] K_r8, K_r9, K_r10, K_r11, K_r12, K_r13, K_r14; + +always @(posedge clk) + begin + K_r0 <= #1 K; + K_r1 <= #1 K_r0; + K_r2 <= #1 K_r1; + K_r3 <= #1 K_r2; + K_r4 <= #1 K_r3; + K_r5 <= #1 K_r4; + K_r6 <= #1 K_r5; + K_r7 <= #1 K_r6; + K_r8 <= #1 K_r7; + K_r9 <= #1 K_r8; + K_r10 <= #1 K_r9; + K_r11 <= #1 K_r10; + K_r12 <= #1 K_r11; + K_r13 <= #1 K_r12; + K_r14 <= #1 K_r13; + end + +assign K16[1] = decrypt ? K_r14[47] : K_r14[40]; +assign K16[2] = decrypt ? K_r14[11] : K_r14[4]; +assign K16[3] = decrypt ? K_r14[26] : K_r14[19]; +assign K16[4] = decrypt ? K_r14[3] : K_r14[53]; +assign K16[5] = decrypt ? K_r14[13] : K_r14[6]; +assign K16[6] = decrypt ? K_r14[41] : K_r14[34]; +assign K16[7] = decrypt ? K_r14[27] : K_r14[20]; +assign K16[8] = decrypt ? K_r14[6] : K_r14[24]; +assign K16[9] = decrypt ? K_r14[54] : K_r14[47]; +assign K16[10] = decrypt ? K_r14[48] : K_r14[41]; +assign K16[11] = decrypt ? K_r14[39] : K_r14[32]; +assign K16[12] = decrypt ? K_r14[19] : K_r14[12]; +assign K16[13] = decrypt ? K_r14[53] : K_r14[46]; +assign K16[14] = decrypt ? K_r14[25] : K_r14[18]; +assign K16[15] = decrypt ? K_r14[33] : K_r14[26]; +assign K16[16] = decrypt ? K_r14[34] : K_r14[27]; +assign K16[17] = decrypt ? K_r14[17] : K_r14[10]; +assign K16[18] = decrypt ? K_r14[5] : K_r14[55]; +assign K16[19] = decrypt ? K_r14[4] : K_r14[54]; +assign K16[20] = decrypt ? K_r14[55] : K_r14[48]; +assign K16[21] = decrypt ? K_r14[24] : K_r14[17]; +assign K16[22] = decrypt ? K_r14[32] : K_r14[25]; +assign K16[23] = decrypt ? K_r14[40] : K_r14[33]; +assign K16[24] = decrypt ? K_r14[20] : K_r14[13]; +assign K16[25] = decrypt ? K_r14[36] : K_r14[29]; +assign K16[26] = decrypt ? K_r14[31] : K_r14[51]; +assign K16[27] = decrypt ? K_r14[21] : K_r14[14]; +assign K16[28] = decrypt ? K_r14[8] : K_r14[1]; +assign K16[29] = decrypt ? K_r14[23] : K_r14[16]; +assign K16[30] = decrypt ? K_r14[52] : K_r14[45]; +assign K16[31] = decrypt ? K_r14[14] : K_r14[7]; +assign K16[32] = decrypt ? K_r14[29] : K_r14[22]; +assign K16[33] = decrypt ? K_r14[51] : K_r14[44]; +assign K16[34] = decrypt ? K_r14[9] : K_r14[2]; +assign K16[35] = decrypt ? K_r14[35] : K_r14[28]; +assign K16[36] = decrypt ? K_r14[30] : K_r14[23]; +assign K16[37] = decrypt ? K_r14[2] : K_r14[50]; +assign K16[38] = decrypt ? K_r14[37] : K_r14[30]; +assign K16[39] = decrypt ? K_r14[22] : K_r14[15]; +assign K16[40] = decrypt ? K_r14[0] : K_r14[52]; +assign K16[41] = decrypt ? K_r14[42] : K_r14[35]; +assign K16[42] = decrypt ? K_r14[38] : K_r14[31]; +assign K16[43] = decrypt ? K_r14[16] : K_r14[9]; +assign K16[44] = decrypt ? K_r14[43] : K_r14[36]; +assign K16[45] = decrypt ? K_r14[44] : K_r14[37]; +assign K16[46] = decrypt ? K_r14[1] : K_r14[49]; +assign K16[47] = decrypt ? K_r14[7] : K_r14[0]; +assign K16[48] = decrypt ? K_r14[28] : K_r14[21]; + +assign K15[1] = decrypt ? K_r13[54] : K_r13[33]; +assign K15[2] = decrypt ? K_r13[18] : K_r13[54]; +assign K15[3] = decrypt ? K_r13[33] : K_r13[12]; +assign K15[4] = decrypt ? K_r13[10] : K_r13[46]; +assign K15[5] = decrypt ? K_r13[20] : K_r13[24]; +assign K15[6] = decrypt ? K_r13[48] : K_r13[27]; +assign K15[7] = decrypt ? K_r13[34] : K_r13[13]; +assign K15[8] = decrypt ? K_r13[13] : K_r13[17]; +assign K15[9] = decrypt ? K_r13[4] : K_r13[40]; +assign K15[10] = decrypt ? K_r13[55] : K_r13[34]; +assign K15[11] = decrypt ? K_r13[46] : K_r13[25]; +assign K15[12] = decrypt ? K_r13[26] : K_r13[5]; +assign K15[13] = decrypt ? K_r13[3] : K_r13[39]; +assign K15[14] = decrypt ? K_r13[32] : K_r13[11]; +assign K15[15] = decrypt ? K_r13[40] : K_r13[19]; +assign K15[16] = decrypt ? K_r13[41] : K_r13[20]; +assign K15[17] = decrypt ? K_r13[24] : K_r13[3]; +assign K15[18] = decrypt ? K_r13[12] : K_r13[48]; +assign K15[19] = decrypt ? K_r13[11] : K_r13[47]; +assign K15[20] = decrypt ? K_r13[5] : K_r13[41]; +assign K15[21] = decrypt ? K_r13[6] : K_r13[10]; +assign K15[22] = decrypt ? K_r13[39] : K_r13[18]; +assign K15[23] = decrypt ? K_r13[47] : K_r13[26]; +assign K15[24] = decrypt ? K_r13[27] : K_r13[6]; +assign K15[25] = decrypt ? K_r13[43] : K_r13[22]; +assign K15[26] = decrypt ? K_r13[38] : K_r13[44]; +assign K15[27] = decrypt ? K_r13[28] : K_r13[7]; +assign K15[28] = decrypt ? K_r13[15] : K_r13[49]; +assign K15[29] = decrypt ? K_r13[30] : K_r13[9]; +assign K15[30] = decrypt ? K_r13[0] : K_r13[38]; +assign K15[31] = decrypt ? K_r13[21] : K_r13[0]; +assign K15[32] = decrypt ? K_r13[36] : K_r13[15]; +assign K15[33] = decrypt ? K_r13[31] : K_r13[37]; +assign K15[34] = decrypt ? K_r13[16] : K_r13[50]; +assign K15[35] = decrypt ? K_r13[42] : K_r13[21]; +assign K15[36] = decrypt ? K_r13[37] : K_r13[16]; +assign K15[37] = decrypt ? K_r13[9] : K_r13[43]; +assign K15[38] = decrypt ? K_r13[44] : K_r13[23]; +assign K15[39] = decrypt ? K_r13[29] : K_r13[8]; +assign K15[40] = decrypt ? K_r13[7] : K_r13[45]; +assign K15[41] = decrypt ? K_r13[49] : K_r13[28]; +assign K15[42] = decrypt ? K_r13[45] : K_r13[51]; +assign K15[43] = decrypt ? K_r13[23] : K_r13[2]; +assign K15[44] = decrypt ? K_r13[50] : K_r13[29]; +assign K15[45] = decrypt ? K_r13[51] : K_r13[30]; +assign K15[46] = decrypt ? K_r13[8] : K_r13[42]; +assign K15[47] = decrypt ? K_r13[14] : K_r13[52]; +assign K15[48] = decrypt ? K_r13[35] : K_r13[14]; + +assign K14[1] = decrypt ? K_r12[11] : K_r12[19]; +assign K14[2] = decrypt ? K_r12[32] : K_r12[40]; +assign K14[3] = decrypt ? K_r12[47] : K_r12[55]; +assign K14[4] = decrypt ? K_r12[24] : K_r12[32]; +assign K14[5] = decrypt ? K_r12[34] : K_r12[10]; +assign K14[6] = decrypt ? K_r12[5] : K_r12[13]; +assign K14[7] = decrypt ? K_r12[48] : K_r12[24]; +assign K14[8] = decrypt ? K_r12[27] : K_r12[3]; +assign K14[9] = decrypt ? K_r12[18] : K_r12[26]; +assign K14[10] = decrypt ? K_r12[12] : K_r12[20]; +assign K14[11] = decrypt ? K_r12[3] : K_r12[11]; +assign K14[12] = decrypt ? K_r12[40] : K_r12[48]; +assign K14[13] = decrypt ? K_r12[17] : K_r12[25]; +assign K14[14] = decrypt ? K_r12[46] : K_r12[54]; +assign K14[15] = decrypt ? K_r12[54] : K_r12[5]; +assign K14[16] = decrypt ? K_r12[55] : K_r12[6]; +assign K14[17] = decrypt ? K_r12[13] : K_r12[46]; +assign K14[18] = decrypt ? K_r12[26] : K_r12[34]; +assign K14[19] = decrypt ? K_r12[25] : K_r12[33]; +assign K14[20] = decrypt ? K_r12[19] : K_r12[27]; +assign K14[21] = decrypt ? K_r12[20] : K_r12[53]; +assign K14[22] = decrypt ? K_r12[53] : K_r12[4]; +assign K14[23] = decrypt ? K_r12[4] : K_r12[12]; +assign K14[24] = decrypt ? K_r12[41] : K_r12[17]; +assign K14[25] = decrypt ? K_r12[2] : K_r12[8]; +assign K14[26] = decrypt ? K_r12[52] : K_r12[30]; +assign K14[27] = decrypt ? K_r12[42] : K_r12[52]; +assign K14[28] = decrypt ? K_r12[29] : K_r12[35]; +assign K14[29] = decrypt ? K_r12[44] : K_r12[50]; +assign K14[30] = decrypt ? K_r12[14] : K_r12[51]; +assign K14[31] = decrypt ? K_r12[35] : K_r12[45]; +assign K14[32] = decrypt ? K_r12[50] : K_r12[1]; +assign K14[33] = decrypt ? K_r12[45] : K_r12[23]; +assign K14[34] = decrypt ? K_r12[30] : K_r12[36]; +assign K14[35] = decrypt ? K_r12[1] : K_r12[7]; +assign K14[36] = decrypt ? K_r12[51] : K_r12[2]; +assign K14[37] = decrypt ? K_r12[23] : K_r12[29]; +assign K14[38] = decrypt ? K_r12[31] : K_r12[9]; +assign K14[39] = decrypt ? K_r12[43] : K_r12[49]; +assign K14[40] = decrypt ? K_r12[21] : K_r12[31]; +assign K14[41] = decrypt ? K_r12[8] : K_r12[14]; +assign K14[42] = decrypt ? K_r12[0] : K_r12[37]; +assign K14[43] = decrypt ? K_r12[37] : K_r12[43]; +assign K14[44] = decrypt ? K_r12[9] : K_r12[15]; +assign K14[45] = decrypt ? K_r12[38] : K_r12[16]; +assign K14[46] = decrypt ? K_r12[22] : K_r12[28]; +assign K14[47] = decrypt ? K_r12[28] : K_r12[38]; +assign K14[48] = decrypt ? K_r12[49] : K_r12[0]; + +assign K13[1] = decrypt ? K_r11[25] : K_r11[5]; +assign K13[2] = decrypt ? K_r11[46] : K_r11[26]; +assign K13[3] = decrypt ? K_r11[4] : K_r11[41]; +assign K13[4] = decrypt ? K_r11[13] : K_r11[18]; +assign K13[5] = decrypt ? K_r11[48] : K_r11[53]; +assign K13[6] = decrypt ? K_r11[19] : K_r11[24]; +assign K13[7] = decrypt ? K_r11[5] : K_r11[10]; +assign K13[8] = decrypt ? K_r11[41] : K_r11[46]; +assign K13[9] = decrypt ? K_r11[32] : K_r11[12]; +assign K13[10] = decrypt ? K_r11[26] : K_r11[6]; +assign K13[11] = decrypt ? K_r11[17] : K_r11[54]; +assign K13[12] = decrypt ? K_r11[54] : K_r11[34]; +assign K13[13] = decrypt ? K_r11[6] : K_r11[11]; +assign K13[14] = decrypt ? K_r11[3] : K_r11[40]; +assign K13[15] = decrypt ? K_r11[11] : K_r11[48]; +assign K13[16] = decrypt ? K_r11[12] : K_r11[17]; +assign K13[17] = decrypt ? K_r11[27] : K_r11[32]; +assign K13[18] = decrypt ? K_r11[40] : K_r11[20]; +assign K13[19] = decrypt ? K_r11[39] : K_r11[19]; +assign K13[20] = decrypt ? K_r11[33] : K_r11[13]; +assign K13[21] = decrypt ? K_r11[34] : K_r11[39]; +assign K13[22] = decrypt ? K_r11[10] : K_r11[47]; +assign K13[23] = decrypt ? K_r11[18] : K_r11[55]; +assign K13[24] = decrypt ? K_r11[55] : K_r11[3]; +assign K13[25] = decrypt ? K_r11[16] : K_r11[49]; +assign K13[26] = decrypt ? K_r11[7] : K_r11[16]; +assign K13[27] = decrypt ? K_r11[1] : K_r11[38]; +assign K13[28] = decrypt ? K_r11[43] : K_r11[21]; +assign K13[29] = decrypt ? K_r11[31] : K_r11[36]; +assign K13[30] = decrypt ? K_r11[28] : K_r11[37]; +assign K13[31] = decrypt ? K_r11[49] : K_r11[31]; +assign K13[32] = decrypt ? K_r11[9] : K_r11[42]; +assign K13[33] = decrypt ? K_r11[0] : K_r11[9]; +assign K13[34] = decrypt ? K_r11[44] : K_r11[22]; +assign K13[35] = decrypt ? K_r11[15] : K_r11[52]; +assign K13[36] = decrypt ? K_r11[38] : K_r11[43]; +assign K13[37] = decrypt ? K_r11[37] : K_r11[15]; +assign K13[38] = decrypt ? K_r11[45] : K_r11[50]; +assign K13[39] = decrypt ? K_r11[2] : K_r11[35]; +assign K13[40] = decrypt ? K_r11[35] : K_r11[44]; +assign K13[41] = decrypt ? K_r11[22] : K_r11[0]; +assign K13[42] = decrypt ? K_r11[14] : K_r11[23]; +assign K13[43] = decrypt ? K_r11[51] : K_r11[29]; +assign K13[44] = decrypt ? K_r11[23] : K_r11[1]; +assign K13[45] = decrypt ? K_r11[52] : K_r11[2]; +assign K13[46] = decrypt ? K_r11[36] : K_r11[14]; +assign K13[47] = decrypt ? K_r11[42] : K_r11[51]; +assign K13[48] = decrypt ? K_r11[8] : K_r11[45]; + +assign K12[1] = decrypt ? K_r10[39] : K_r10[48]; +assign K12[2] = decrypt ? K_r10[3] : K_r10[12]; +assign K12[3] = decrypt ? K_r10[18] : K_r10[27]; +assign K12[4] = decrypt ? K_r10[27] : K_r10[4]; +assign K12[5] = decrypt ? K_r10[5] : K_r10[39]; +assign K12[6] = decrypt ? K_r10[33] : K_r10[10]; +assign K12[7] = decrypt ? K_r10[19] : K_r10[53]; +assign K12[8] = decrypt ? K_r10[55] : K_r10[32]; +assign K12[9] = decrypt ? K_r10[46] : K_r10[55]; +assign K12[10] = decrypt ? K_r10[40] : K_r10[17]; +assign K12[11] = decrypt ? K_r10[6] : K_r10[40]; +assign K12[12] = decrypt ? K_r10[11] : K_r10[20]; +assign K12[13] = decrypt ? K_r10[20] : K_r10[54]; +assign K12[14] = decrypt ? K_r10[17] : K_r10[26]; +assign K12[15] = decrypt ? K_r10[25] : K_r10[34]; +assign K12[16] = decrypt ? K_r10[26] : K_r10[3]; +assign K12[17] = decrypt ? K_r10[41] : K_r10[18]; +assign K12[18] = decrypt ? K_r10[54] : K_r10[6]; +assign K12[19] = decrypt ? K_r10[53] : K_r10[5]; +assign K12[20] = decrypt ? K_r10[47] : K_r10[24]; +assign K12[21] = decrypt ? K_r10[48] : K_r10[25]; +assign K12[22] = decrypt ? K_r10[24] : K_r10[33]; +assign K12[23] = decrypt ? K_r10[32] : K_r10[41]; +assign K12[24] = decrypt ? K_r10[12] : K_r10[46]; +assign K12[25] = decrypt ? K_r10[30] : K_r10[35]; +assign K12[26] = decrypt ? K_r10[21] : K_r10[2]; +assign K12[27] = decrypt ? K_r10[15] : K_r10[51]; +assign K12[28] = decrypt ? K_r10[2] : K_r10[7]; +assign K12[29] = decrypt ? K_r10[45] : K_r10[22]; +assign K12[30] = decrypt ? K_r10[42] : K_r10[23]; +assign K12[31] = decrypt ? K_r10[8] : K_r10[44]; +assign K12[32] = decrypt ? K_r10[23] : K_r10[28]; +assign K12[33] = decrypt ? K_r10[14] : K_r10[50]; +assign K12[34] = decrypt ? K_r10[31] : K_r10[8]; +assign K12[35] = decrypt ? K_r10[29] : K_r10[38]; +assign K12[36] = decrypt ? K_r10[52] : K_r10[29]; +assign K12[37] = decrypt ? K_r10[51] : K_r10[1]; +assign K12[38] = decrypt ? K_r10[0] : K_r10[36]; +assign K12[39] = decrypt ? K_r10[16] : K_r10[21]; +assign K12[40] = decrypt ? K_r10[49] : K_r10[30]; +assign K12[41] = decrypt ? K_r10[36] : K_r10[45]; +assign K12[42] = decrypt ? K_r10[28] : K_r10[9]; +assign K12[43] = decrypt ? K_r10[38] : K_r10[15]; +assign K12[44] = decrypt ? K_r10[37] : K_r10[42]; +assign K12[45] = decrypt ? K_r10[7] : K_r10[43]; +assign K12[46] = decrypt ? K_r10[50] : K_r10[0]; +assign K12[47] = decrypt ? K_r10[1] : K_r10[37]; +assign K12[48] = decrypt ? K_r10[22] : K_r10[31]; + +assign K11[1] = decrypt ? K_r9[53] : K_r9[34]; +assign K11[2] = decrypt ? K_r9[17] : K_r9[55]; +assign K11[3] = decrypt ? K_r9[32] : K_r9[13]; +assign K11[4] = decrypt ? K_r9[41] : K_r9[47]; +assign K11[5] = decrypt ? K_r9[19] : K_r9[25]; +assign K11[6] = decrypt ? K_r9[47] : K_r9[53]; +assign K11[7] = decrypt ? K_r9[33] : K_r9[39]; +assign K11[8] = decrypt ? K_r9[12] : K_r9[18]; +assign K11[9] = decrypt ? K_r9[3] : K_r9[41]; +assign K11[10] = decrypt ? K_r9[54] : K_r9[3]; +assign K11[11] = decrypt ? K_r9[20] : K_r9[26]; +assign K11[12] = decrypt ? K_r9[25] : K_r9[6]; +assign K11[13] = decrypt ? K_r9[34] : K_r9[40]; +assign K11[14] = decrypt ? K_r9[6] : K_r9[12]; +assign K11[15] = decrypt ? K_r9[39] : K_r9[20]; +assign K11[16] = decrypt ? K_r9[40] : K_r9[46]; +assign K11[17] = decrypt ? K_r9[55] : K_r9[4]; +assign K11[18] = decrypt ? K_r9[11] : K_r9[17]; +assign K11[19] = decrypt ? K_r9[10] : K_r9[48]; +assign K11[20] = decrypt ? K_r9[4] : K_r9[10]; +assign K11[21] = decrypt ? K_r9[5] : K_r9[11]; +assign K11[22] = decrypt ? K_r9[13] : K_r9[19]; +assign K11[23] = decrypt ? K_r9[46] : K_r9[27]; +assign K11[24] = decrypt ? K_r9[26] : K_r9[32]; +assign K11[25] = decrypt ? K_r9[44] : K_r9[21]; +assign K11[26] = decrypt ? K_r9[35] : K_r9[43]; +assign K11[27] = decrypt ? K_r9[29] : K_r9[37]; +assign K11[28] = decrypt ? K_r9[16] : K_r9[52]; +assign K11[29] = decrypt ? K_r9[0] : K_r9[8]; +assign K11[30] = decrypt ? K_r9[1] : K_r9[9]; +assign K11[31] = decrypt ? K_r9[22] : K_r9[30]; +assign K11[32] = decrypt ? K_r9[37] : K_r9[14]; +assign K11[33] = decrypt ? K_r9[28] : K_r9[36]; +assign K11[34] = decrypt ? K_r9[45] : K_r9[49]; +assign K11[35] = decrypt ? K_r9[43] : K_r9[51]; +assign K11[36] = decrypt ? K_r9[7] : K_r9[15]; +assign K11[37] = decrypt ? K_r9[38] : K_r9[42]; +assign K11[38] = decrypt ? K_r9[14] : K_r9[22]; +assign K11[39] = decrypt ? K_r9[30] : K_r9[7]; +assign K11[40] = decrypt ? K_r9[8] : K_r9[16]; +assign K11[41] = decrypt ? K_r9[50] : K_r9[31]; +assign K11[42] = decrypt ? K_r9[42] : K_r9[50]; +assign K11[43] = decrypt ? K_r9[52] : K_r9[1]; +assign K11[44] = decrypt ? K_r9[51] : K_r9[28]; +assign K11[45] = decrypt ? K_r9[21] : K_r9[29]; +assign K11[46] = decrypt ? K_r9[9] : K_r9[45]; +assign K11[47] = decrypt ? K_r9[15] : K_r9[23]; +assign K11[48] = decrypt ? K_r9[36] : K_r9[44]; + +assign K10[1] = decrypt ? K_r8[10] : K_r8[20]; +assign K10[2] = decrypt ? K_r8[6] : K_r8[41]; +assign K10[3] = decrypt ? K_r8[46] : K_r8[24]; +assign K10[4] = decrypt ? K_r8[55] : K_r8[33]; +assign K10[5] = decrypt ? K_r8[33] : K_r8[11]; +assign K10[6] = decrypt ? K_r8[4] : K_r8[39]; +assign K10[7] = decrypt ? K_r8[47] : K_r8[25]; +assign K10[8] = decrypt ? K_r8[26] : K_r8[4]; +assign K10[9] = decrypt ? K_r8[17] : K_r8[27]; +assign K10[10] = decrypt ? K_r8[11] : K_r8[46]; +assign K10[11] = decrypt ? K_r8[34] : K_r8[12]; +assign K10[12] = decrypt ? K_r8[39] : K_r8[17]; +assign K10[13] = decrypt ? K_r8[48] : K_r8[26]; +assign K10[14] = decrypt ? K_r8[20] : K_r8[55]; +assign K10[15] = decrypt ? K_r8[53] : K_r8[6]; +assign K10[16] = decrypt ? K_r8[54] : K_r8[32]; +assign K10[17] = decrypt ? K_r8[12] : K_r8[47]; +assign K10[18] = decrypt ? K_r8[25] : K_r8[3]; +assign K10[19] = decrypt ? K_r8[24] : K_r8[34]; +assign K10[20] = decrypt ? K_r8[18] : K_r8[53]; +assign K10[21] = decrypt ? K_r8[19] : K_r8[54]; +assign K10[22] = decrypt ? K_r8[27] : K_r8[5]; +assign K10[23] = decrypt ? K_r8[3] : K_r8[13]; +assign K10[24] = decrypt ? K_r8[40] : K_r8[18]; +assign K10[25] = decrypt ? K_r8[31] : K_r8[7]; +assign K10[26] = decrypt ? K_r8[49] : K_r8[29]; +assign K10[27] = decrypt ? K_r8[43] : K_r8[23]; +assign K10[28] = decrypt ? K_r8[30] : K_r8[38]; +assign K10[29] = decrypt ? K_r8[14] : K_r8[49]; +assign K10[30] = decrypt ? K_r8[15] : K_r8[50]; +assign K10[31] = decrypt ? K_r8[36] : K_r8[16]; +assign K10[32] = decrypt ? K_r8[51] : K_r8[0]; +assign K10[33] = decrypt ? K_r8[42] : K_r8[22]; +assign K10[34] = decrypt ? K_r8[0] : K_r8[35]; +assign K10[35] = decrypt ? K_r8[2] : K_r8[37]; +assign K10[36] = decrypt ? K_r8[21] : K_r8[1]; +assign K10[37] = decrypt ? K_r8[52] : K_r8[28]; +assign K10[38] = decrypt ? K_r8[28] : K_r8[8]; +assign K10[39] = decrypt ? K_r8[44] : K_r8[52]; +assign K10[40] = decrypt ? K_r8[22] : K_r8[2]; +assign K10[41] = decrypt ? K_r8[9] : K_r8[44]; +assign K10[42] = decrypt ? K_r8[1] : K_r8[36]; +assign K10[43] = decrypt ? K_r8[7] : K_r8[42]; +assign K10[44] = decrypt ? K_r8[38] : K_r8[14]; +assign K10[45] = decrypt ? K_r8[35] : K_r8[15]; +assign K10[46] = decrypt ? K_r8[23] : K_r8[31]; +assign K10[47] = decrypt ? K_r8[29] : K_r8[9]; +assign K10[48] = decrypt ? K_r8[50] : K_r8[30]; + +assign K9[1] = decrypt ? K_r7[24] : K_r7[6]; +assign K9[2] = decrypt ? K_r7[20] : K_r7[27]; +assign K9[3] = decrypt ? K_r7[3] : K_r7[10]; +assign K9[4] = decrypt ? K_r7[12] : K_r7[19]; +assign K9[5] = decrypt ? K_r7[47] : K_r7[54]; +assign K9[6] = decrypt ? K_r7[18] : K_r7[25]; +assign K9[7] = decrypt ? K_r7[4] : K_r7[11]; +assign K9[8] = decrypt ? K_r7[40] : K_r7[47]; +assign K9[9] = decrypt ? K_r7[6] : K_r7[13]; +assign K9[10] = decrypt ? K_r7[25] : K_r7[32]; +assign K9[11] = decrypt ? K_r7[48] : K_r7[55]; +assign K9[12] = decrypt ? K_r7[53] : K_r7[3]; +assign K9[13] = decrypt ? K_r7[5] : K_r7[12]; +assign K9[14] = decrypt ? K_r7[34] : K_r7[41]; +assign K9[15] = decrypt ? K_r7[10] : K_r7[17]; +assign K9[16] = decrypt ? K_r7[11] : K_r7[18]; +assign K9[17] = decrypt ? K_r7[26] : K_r7[33]; +assign K9[18] = decrypt ? K_r7[39] : K_r7[46]; +assign K9[19] = decrypt ? K_r7[13] : K_r7[20]; +assign K9[20] = decrypt ? K_r7[32] : K_r7[39]; +assign K9[21] = decrypt ? K_r7[33] : K_r7[40]; +assign K9[22] = decrypt ? K_r7[41] : K_r7[48]; +assign K9[23] = decrypt ? K_r7[17] : K_r7[24]; +assign K9[24] = decrypt ? K_r7[54] : K_r7[4]; +assign K9[25] = decrypt ? K_r7[45] : K_r7[52]; +assign K9[26] = decrypt ? K_r7[8] : K_r7[15]; +assign K9[27] = decrypt ? K_r7[2] : K_r7[9]; +assign K9[28] = decrypt ? K_r7[44] : K_r7[51]; +assign K9[29] = decrypt ? K_r7[28] : K_r7[35]; +assign K9[30] = decrypt ? K_r7[29] : K_r7[36]; +assign K9[31] = decrypt ? K_r7[50] : K_r7[2]; +assign K9[32] = decrypt ? K_r7[38] : K_r7[45]; +assign K9[33] = decrypt ? K_r7[1] : K_r7[8]; +assign K9[34] = decrypt ? K_r7[14] : K_r7[21]; +assign K9[35] = decrypt ? K_r7[16] : K_r7[23]; +assign K9[36] = decrypt ? K_r7[35] : K_r7[42]; +assign K9[37] = decrypt ? K_r7[7] : K_r7[14]; +assign K9[38] = decrypt ? K_r7[42] : K_r7[49]; +assign K9[39] = decrypt ? K_r7[31] : K_r7[38]; +assign K9[40] = decrypt ? K_r7[36] : K_r7[43]; +assign K9[41] = decrypt ? K_r7[23] : K_r7[30]; +assign K9[42] = decrypt ? K_r7[15] : K_r7[22]; +assign K9[43] = decrypt ? K_r7[21] : K_r7[28]; +assign K9[44] = decrypt ? K_r7[52] : K_r7[0]; +assign K9[45] = decrypt ? K_r7[49] : K_r7[1]; +assign K9[46] = decrypt ? K_r7[37] : K_r7[44]; +assign K9[47] = decrypt ? K_r7[43] : K_r7[50]; +assign K9[48] = decrypt ? K_r7[9] : K_r7[16]; + +assign K8[1] = decrypt ? K_r6[6] : K_r6[24]; +assign K8[2] = decrypt ? K_r6[27] : K_r6[20]; +assign K8[3] = decrypt ? K_r6[10] : K_r6[3]; +assign K8[4] = decrypt ? K_r6[19] : K_r6[12]; +assign K8[5] = decrypt ? K_r6[54] : K_r6[47]; +assign K8[6] = decrypt ? K_r6[25] : K_r6[18]; +assign K8[7] = decrypt ? K_r6[11] : K_r6[4]; +assign K8[8] = decrypt ? K_r6[47] : K_r6[40]; +assign K8[9] = decrypt ? K_r6[13] : K_r6[6]; +assign K8[10] = decrypt ? K_r6[32] : K_r6[25]; +assign K8[11] = decrypt ? K_r6[55] : K_r6[48]; +assign K8[12] = decrypt ? K_r6[3] : K_r6[53]; +assign K8[13] = decrypt ? K_r6[12] : K_r6[5]; +assign K8[14] = decrypt ? K_r6[41] : K_r6[34]; +assign K8[15] = decrypt ? K_r6[17] : K_r6[10]; +assign K8[16] = decrypt ? K_r6[18] : K_r6[11]; +assign K8[17] = decrypt ? K_r6[33] : K_r6[26]; +assign K8[18] = decrypt ? K_r6[46] : K_r6[39]; +assign K8[19] = decrypt ? K_r6[20] : K_r6[13]; +assign K8[20] = decrypt ? K_r6[39] : K_r6[32]; +assign K8[21] = decrypt ? K_r6[40] : K_r6[33]; +assign K8[22] = decrypt ? K_r6[48] : K_r6[41]; +assign K8[23] = decrypt ? K_r6[24] : K_r6[17]; +assign K8[24] = decrypt ? K_r6[4] : K_r6[54]; +assign K8[25] = decrypt ? K_r6[52] : K_r6[45]; +assign K8[26] = decrypt ? K_r6[15] : K_r6[8]; +assign K8[27] = decrypt ? K_r6[9] : K_r6[2]; +assign K8[28] = decrypt ? K_r6[51] : K_r6[44]; +assign K8[29] = decrypt ? K_r6[35] : K_r6[28]; +assign K8[30] = decrypt ? K_r6[36] : K_r6[29]; +assign K8[31] = decrypt ? K_r6[2] : K_r6[50]; +assign K8[32] = decrypt ? K_r6[45] : K_r6[38]; +assign K8[33] = decrypt ? K_r6[8] : K_r6[1]; +assign K8[34] = decrypt ? K_r6[21] : K_r6[14]; +assign K8[35] = decrypt ? K_r6[23] : K_r6[16]; +assign K8[36] = decrypt ? K_r6[42] : K_r6[35]; +assign K8[37] = decrypt ? K_r6[14] : K_r6[7]; +assign K8[38] = decrypt ? K_r6[49] : K_r6[42]; +assign K8[39] = decrypt ? K_r6[38] : K_r6[31]; +assign K8[40] = decrypt ? K_r6[43] : K_r6[36]; +assign K8[41] = decrypt ? K_r6[30] : K_r6[23]; +assign K8[42] = decrypt ? K_r6[22] : K_r6[15]; +assign K8[43] = decrypt ? K_r6[28] : K_r6[21]; +assign K8[44] = decrypt ? K_r6[0] : K_r6[52]; +assign K8[45] = decrypt ? K_r6[1] : K_r6[49]; +assign K8[46] = decrypt ? K_r6[44] : K_r6[37]; +assign K8[47] = decrypt ? K_r6[50] : K_r6[43]; +assign K8[48] = decrypt ? K_r6[16] : K_r6[9]; + +assign K7[1] = decrypt ? K_r5[20] : K_r5[10]; +assign K7[2] = decrypt ? K_r5[41] : K_r5[6]; +assign K7[3] = decrypt ? K_r5[24] : K_r5[46]; +assign K7[4] = decrypt ? K_r5[33] : K_r5[55]; +assign K7[5] = decrypt ? K_r5[11] : K_r5[33]; +assign K7[6] = decrypt ? K_r5[39] : K_r5[4]; +assign K7[7] = decrypt ? K_r5[25] : K_r5[47]; +assign K7[8] = decrypt ? K_r5[4] : K_r5[26]; +assign K7[9] = decrypt ? K_r5[27] : K_r5[17]; +assign K7[10] = decrypt ? K_r5[46] : K_r5[11]; +assign K7[11] = decrypt ? K_r5[12] : K_r5[34]; +assign K7[12] = decrypt ? K_r5[17] : K_r5[39]; +assign K7[13] = decrypt ? K_r5[26] : K_r5[48]; +assign K7[14] = decrypt ? K_r5[55] : K_r5[20]; +assign K7[15] = decrypt ? K_r5[6] : K_r5[53]; +assign K7[16] = decrypt ? K_r5[32] : K_r5[54]; +assign K7[17] = decrypt ? K_r5[47] : K_r5[12]; +assign K7[18] = decrypt ? K_r5[3] : K_r5[25]; +assign K7[19] = decrypt ? K_r5[34] : K_r5[24]; +assign K7[20] = decrypt ? K_r5[53] : K_r5[18]; +assign K7[21] = decrypt ? K_r5[54] : K_r5[19]; +assign K7[22] = decrypt ? K_r5[5] : K_r5[27]; +assign K7[23] = decrypt ? K_r5[13] : K_r5[3]; +assign K7[24] = decrypt ? K_r5[18] : K_r5[40]; +assign K7[25] = decrypt ? K_r5[7] : K_r5[31]; +assign K7[26] = decrypt ? K_r5[29] : K_r5[49]; +assign K7[27] = decrypt ? K_r5[23] : K_r5[43]; +assign K7[28] = decrypt ? K_r5[38] : K_r5[30]; +assign K7[29] = decrypt ? K_r5[49] : K_r5[14]; +assign K7[30] = decrypt ? K_r5[50] : K_r5[15]; +assign K7[31] = decrypt ? K_r5[16] : K_r5[36]; +assign K7[32] = decrypt ? K_r5[0] : K_r5[51]; +assign K7[33] = decrypt ? K_r5[22] : K_r5[42]; +assign K7[34] = decrypt ? K_r5[35] : K_r5[0]; +assign K7[35] = decrypt ? K_r5[37] : K_r5[2]; +assign K7[36] = decrypt ? K_r5[1] : K_r5[21]; +assign K7[37] = decrypt ? K_r5[28] : K_r5[52]; +assign K7[38] = decrypt ? K_r5[8] : K_r5[28]; +assign K7[39] = decrypt ? K_r5[52] : K_r5[44]; +assign K7[40] = decrypt ? K_r5[2] : K_r5[22]; +assign K7[41] = decrypt ? K_r5[44] : K_r5[9]; +assign K7[42] = decrypt ? K_r5[36] : K_r5[1]; +assign K7[43] = decrypt ? K_r5[42] : K_r5[7]; +assign K7[44] = decrypt ? K_r5[14] : K_r5[38]; +assign K7[45] = decrypt ? K_r5[15] : K_r5[35]; +assign K7[46] = decrypt ? K_r5[31] : K_r5[23]; +assign K7[47] = decrypt ? K_r5[9] : K_r5[29]; +assign K7[48] = decrypt ? K_r5[30] : K_r5[50]; + +assign K6[1] = decrypt ? K_r4[34] : K_r4[53]; +assign K6[2] = decrypt ? K_r4[55] : K_r4[17]; +assign K6[3] = decrypt ? K_r4[13] : K_r4[32]; +assign K6[4] = decrypt ? K_r4[47] : K_r4[41]; +assign K6[5] = decrypt ? K_r4[25] : K_r4[19]; +assign K6[6] = decrypt ? K_r4[53] : K_r4[47]; +assign K6[7] = decrypt ? K_r4[39] : K_r4[33]; +assign K6[8] = decrypt ? K_r4[18] : K_r4[12]; +assign K6[9] = decrypt ? K_r4[41] : K_r4[3]; +assign K6[10] = decrypt ? K_r4[3] : K_r4[54]; +assign K6[11] = decrypt ? K_r4[26] : K_r4[20]; +assign K6[12] = decrypt ? K_r4[6] : K_r4[25]; +assign K6[13] = decrypt ? K_r4[40] : K_r4[34]; +assign K6[14] = decrypt ? K_r4[12] : K_r4[6]; +assign K6[15] = decrypt ? K_r4[20] : K_r4[39]; +assign K6[16] = decrypt ? K_r4[46] : K_r4[40]; +assign K6[17] = decrypt ? K_r4[4] : K_r4[55]; +assign K6[18] = decrypt ? K_r4[17] : K_r4[11]; +assign K6[19] = decrypt ? K_r4[48] : K_r4[10]; +assign K6[20] = decrypt ? K_r4[10] : K_r4[4]; +assign K6[21] = decrypt ? K_r4[11] : K_r4[5]; +assign K6[22] = decrypt ? K_r4[19] : K_r4[13]; +assign K6[23] = decrypt ? K_r4[27] : K_r4[46]; +assign K6[24] = decrypt ? K_r4[32] : K_r4[26]; +assign K6[25] = decrypt ? K_r4[21] : K_r4[44]; +assign K6[26] = decrypt ? K_r4[43] : K_r4[35]; +assign K6[27] = decrypt ? K_r4[37] : K_r4[29]; +assign K6[28] = decrypt ? K_r4[52] : K_r4[16]; +assign K6[29] = decrypt ? K_r4[8] : K_r4[0]; +assign K6[30] = decrypt ? K_r4[9] : K_r4[1]; +assign K6[31] = decrypt ? K_r4[30] : K_r4[22]; +assign K6[32] = decrypt ? K_r4[14] : K_r4[37]; +assign K6[33] = decrypt ? K_r4[36] : K_r4[28]; +assign K6[34] = decrypt ? K_r4[49] : K_r4[45]; +assign K6[35] = decrypt ? K_r4[51] : K_r4[43]; +assign K6[36] = decrypt ? K_r4[15] : K_r4[7]; +assign K6[37] = decrypt ? K_r4[42] : K_r4[38]; +assign K6[38] = decrypt ? K_r4[22] : K_r4[14]; +assign K6[39] = decrypt ? K_r4[7] : K_r4[30]; +assign K6[40] = decrypt ? K_r4[16] : K_r4[8]; +assign K6[41] = decrypt ? K_r4[31] : K_r4[50]; +assign K6[42] = decrypt ? K_r4[50] : K_r4[42]; +assign K6[43] = decrypt ? K_r4[1] : K_r4[52]; +assign K6[44] = decrypt ? K_r4[28] : K_r4[51]; +assign K6[45] = decrypt ? K_r4[29] : K_r4[21]; +assign K6[46] = decrypt ? K_r4[45] : K_r4[9]; +assign K6[47] = decrypt ? K_r4[23] : K_r4[15]; +assign K6[48] = decrypt ? K_r4[44] : K_r4[36]; + +assign K5[1] = decrypt ? K_r3[48] : K_r3[39]; +assign K5[2] = decrypt ? K_r3[12] : K_r3[3]; +assign K5[3] = decrypt ? K_r3[27] : K_r3[18]; +assign K5[4] = decrypt ? K_r3[4] : K_r3[27]; +assign K5[5] = decrypt ? K_r3[39] : K_r3[5]; +assign K5[6] = decrypt ? K_r3[10] : K_r3[33]; +assign K5[7] = decrypt ? K_r3[53] : K_r3[19]; +assign K5[8] = decrypt ? K_r3[32] : K_r3[55]; +assign K5[9] = decrypt ? K_r3[55] : K_r3[46]; +assign K5[10] = decrypt ? K_r3[17] : K_r3[40]; +assign K5[11] = decrypt ? K_r3[40] : K_r3[6]; +assign K5[12] = decrypt ? K_r3[20] : K_r3[11]; +assign K5[13] = decrypt ? K_r3[54] : K_r3[20]; +assign K5[14] = decrypt ? K_r3[26] : K_r3[17]; +assign K5[15] = decrypt ? K_r3[34] : K_r3[25]; +assign K5[16] = decrypt ? K_r3[3] : K_r3[26]; +assign K5[17] = decrypt ? K_r3[18] : K_r3[41]; +assign K5[18] = decrypt ? K_r3[6] : K_r3[54]; +assign K5[19] = decrypt ? K_r3[5] : K_r3[53]; +assign K5[20] = decrypt ? K_r3[24] : K_r3[47]; +assign K5[21] = decrypt ? K_r3[25] : K_r3[48]; +assign K5[22] = decrypt ? K_r3[33] : K_r3[24]; +assign K5[23] = decrypt ? K_r3[41] : K_r3[32]; +assign K5[24] = decrypt ? K_r3[46] : K_r3[12]; +assign K5[25] = decrypt ? K_r3[35] : K_r3[30]; +assign K5[26] = decrypt ? K_r3[2] : K_r3[21]; +assign K5[27] = decrypt ? K_r3[51] : K_r3[15]; +assign K5[28] = decrypt ? K_r3[7] : K_r3[2]; +assign K5[29] = decrypt ? K_r3[22] : K_r3[45]; +assign K5[30] = decrypt ? K_r3[23] : K_r3[42]; +assign K5[31] = decrypt ? K_r3[44] : K_r3[8]; +assign K5[32] = decrypt ? K_r3[28] : K_r3[23]; +assign K5[33] = decrypt ? K_r3[50] : K_r3[14]; +assign K5[34] = decrypt ? K_r3[8] : K_r3[31]; +assign K5[35] = decrypt ? K_r3[38] : K_r3[29]; +assign K5[36] = decrypt ? K_r3[29] : K_r3[52]; +assign K5[37] = decrypt ? K_r3[1] : K_r3[51]; +assign K5[38] = decrypt ? K_r3[36] : K_r3[0]; +assign K5[39] = decrypt ? K_r3[21] : K_r3[16]; +assign K5[40] = decrypt ? K_r3[30] : K_r3[49]; +assign K5[41] = decrypt ? K_r3[45] : K_r3[36]; +assign K5[42] = decrypt ? K_r3[9] : K_r3[28]; +assign K5[43] = decrypt ? K_r3[15] : K_r3[38]; +assign K5[44] = decrypt ? K_r3[42] : K_r3[37]; +assign K5[45] = decrypt ? K_r3[43] : K_r3[7]; +assign K5[46] = decrypt ? K_r3[0] : K_r3[50]; +assign K5[47] = decrypt ? K_r3[37] : K_r3[1]; +assign K5[48] = decrypt ? K_r3[31] : K_r3[22]; + +assign K4[1] = decrypt ? K_r2[5] : K_r2[25]; +assign K4[2] = decrypt ? K_r2[26] : K_r2[46]; +assign K4[3] = decrypt ? K_r2[41] : K_r2[4]; +assign K4[4] = decrypt ? K_r2[18] : K_r2[13]; +assign K4[5] = decrypt ? K_r2[53] : K_r2[48]; +assign K4[6] = decrypt ? K_r2[24] : K_r2[19]; +assign K4[7] = decrypt ? K_r2[10] : K_r2[5]; +assign K4[8] = decrypt ? K_r2[46] : K_r2[41]; +assign K4[9] = decrypt ? K_r2[12] : K_r2[32]; +assign K4[10] = decrypt ? K_r2[6] : K_r2[26]; +assign K4[11] = decrypt ? K_r2[54] : K_r2[17]; +assign K4[12] = decrypt ? K_r2[34] : K_r2[54]; +assign K4[13] = decrypt ? K_r2[11] : K_r2[6]; +assign K4[14] = decrypt ? K_r2[40] : K_r2[3]; +assign K4[15] = decrypt ? K_r2[48] : K_r2[11]; +assign K4[16] = decrypt ? K_r2[17] : K_r2[12]; +assign K4[17] = decrypt ? K_r2[32] : K_r2[27]; +assign K4[18] = decrypt ? K_r2[20] : K_r2[40]; +assign K4[19] = decrypt ? K_r2[19] : K_r2[39]; +assign K4[20] = decrypt ? K_r2[13] : K_r2[33]; +assign K4[21] = decrypt ? K_r2[39] : K_r2[34]; +assign K4[22] = decrypt ? K_r2[47] : K_r2[10]; +assign K4[23] = decrypt ? K_r2[55] : K_r2[18]; +assign K4[24] = decrypt ? K_r2[3] : K_r2[55]; +assign K4[25] = decrypt ? K_r2[49] : K_r2[16]; +assign K4[26] = decrypt ? K_r2[16] : K_r2[7]; +assign K4[27] = decrypt ? K_r2[38] : K_r2[1]; +assign K4[28] = decrypt ? K_r2[21] : K_r2[43]; +assign K4[29] = decrypt ? K_r2[36] : K_r2[31]; +assign K4[30] = decrypt ? K_r2[37] : K_r2[28]; +assign K4[31] = decrypt ? K_r2[31] : K_r2[49]; +assign K4[32] = decrypt ? K_r2[42] : K_r2[9]; +assign K4[33] = decrypt ? K_r2[9] : K_r2[0]; +assign K4[34] = decrypt ? K_r2[22] : K_r2[44]; +assign K4[35] = decrypt ? K_r2[52] : K_r2[15]; +assign K4[36] = decrypt ? K_r2[43] : K_r2[38]; +assign K4[37] = decrypt ? K_r2[15] : K_r2[37]; +assign K4[38] = decrypt ? K_r2[50] : K_r2[45]; +assign K4[39] = decrypt ? K_r2[35] : K_r2[2]; +assign K4[40] = decrypt ? K_r2[44] : K_r2[35]; +assign K4[41] = decrypt ? K_r2[0] : K_r2[22]; +assign K4[42] = decrypt ? K_r2[23] : K_r2[14]; +assign K4[43] = decrypt ? K_r2[29] : K_r2[51]; +assign K4[44] = decrypt ? K_r2[1] : K_r2[23]; +assign K4[45] = decrypt ? K_r2[2] : K_r2[52]; +assign K4[46] = decrypt ? K_r2[14] : K_r2[36]; +assign K4[47] = decrypt ? K_r2[51] : K_r2[42]; +assign K4[48] = decrypt ? K_r2[45] : K_r2[8]; + +assign K3[1] = decrypt ? K_r1[19] : K_r1[11]; +assign K3[2] = decrypt ? K_r1[40] : K_r1[32]; +assign K3[3] = decrypt ? K_r1[55] : K_r1[47]; +assign K3[4] = decrypt ? K_r1[32] : K_r1[24]; +assign K3[5] = decrypt ? K_r1[10] : K_r1[34]; +assign K3[6] = decrypt ? K_r1[13] : K_r1[5]; +assign K3[7] = decrypt ? K_r1[24] : K_r1[48]; +assign K3[8] = decrypt ? K_r1[3] : K_r1[27]; +assign K3[9] = decrypt ? K_r1[26] : K_r1[18]; +assign K3[10] = decrypt ? K_r1[20] : K_r1[12]; +assign K3[11] = decrypt ? K_r1[11] : K_r1[3]; +assign K3[12] = decrypt ? K_r1[48] : K_r1[40]; +assign K3[13] = decrypt ? K_r1[25] : K_r1[17]; +assign K3[14] = decrypt ? K_r1[54] : K_r1[46]; +assign K3[15] = decrypt ? K_r1[5] : K_r1[54]; +assign K3[16] = decrypt ? K_r1[6] : K_r1[55]; +assign K3[17] = decrypt ? K_r1[46] : K_r1[13]; +assign K3[18] = decrypt ? K_r1[34] : K_r1[26]; +assign K3[19] = decrypt ? K_r1[33] : K_r1[25]; +assign K3[20] = decrypt ? K_r1[27] : K_r1[19]; +assign K3[21] = decrypt ? K_r1[53] : K_r1[20]; +assign K3[22] = decrypt ? K_r1[4] : K_r1[53]; +assign K3[23] = decrypt ? K_r1[12] : K_r1[4]; +assign K3[24] = decrypt ? K_r1[17] : K_r1[41]; +assign K3[25] = decrypt ? K_r1[8] : K_r1[2]; +assign K3[26] = decrypt ? K_r1[30] : K_r1[52]; +assign K3[27] = decrypt ? K_r1[52] : K_r1[42]; +assign K3[28] = decrypt ? K_r1[35] : K_r1[29]; +assign K3[29] = decrypt ? K_r1[50] : K_r1[44]; +assign K3[30] = decrypt ? K_r1[51] : K_r1[14]; +assign K3[31] = decrypt ? K_r1[45] : K_r1[35]; +assign K3[32] = decrypt ? K_r1[1] : K_r1[50]; +assign K3[33] = decrypt ? K_r1[23] : K_r1[45]; +assign K3[34] = decrypt ? K_r1[36] : K_r1[30]; +assign K3[35] = decrypt ? K_r1[7] : K_r1[1]; +assign K3[36] = decrypt ? K_r1[2] : K_r1[51]; +assign K3[37] = decrypt ? K_r1[29] : K_r1[23]; +assign K3[38] = decrypt ? K_r1[9] : K_r1[31]; +assign K3[39] = decrypt ? K_r1[49] : K_r1[43]; +assign K3[40] = decrypt ? K_r1[31] : K_r1[21]; +assign K3[41] = decrypt ? K_r1[14] : K_r1[8]; +assign K3[42] = decrypt ? K_r1[37] : K_r1[0]; +assign K3[43] = decrypt ? K_r1[43] : K_r1[37]; +assign K3[44] = decrypt ? K_r1[15] : K_r1[9]; +assign K3[45] = decrypt ? K_r1[16] : K_r1[38]; +assign K3[46] = decrypt ? K_r1[28] : K_r1[22]; +assign K3[47] = decrypt ? K_r1[38] : K_r1[28]; +assign K3[48] = decrypt ? K_r1[0] : K_r1[49]; + +assign K2[1] = decrypt ? K_r0[33] : K_r0[54]; +assign K2[2] = decrypt ? K_r0[54] : K_r0[18]; +assign K2[3] = decrypt ? K_r0[12] : K_r0[33]; +assign K2[4] = decrypt ? K_r0[46] : K_r0[10]; +assign K2[5] = decrypt ? K_r0[24] : K_r0[20]; +assign K2[6] = decrypt ? K_r0[27] : K_r0[48]; +assign K2[7] = decrypt ? K_r0[13] : K_r0[34]; +assign K2[8] = decrypt ? K_r0[17] : K_r0[13]; +assign K2[9] = decrypt ? K_r0[40] : K_r0[4]; +assign K2[10] = decrypt ? K_r0[34] : K_r0[55]; +assign K2[11] = decrypt ? K_r0[25] : K_r0[46]; +assign K2[12] = decrypt ? K_r0[5] : K_r0[26]; +assign K2[13] = decrypt ? K_r0[39] : K_r0[3]; +assign K2[14] = decrypt ? K_r0[11] : K_r0[32]; +assign K2[15] = decrypt ? K_r0[19] : K_r0[40]; +assign K2[16] = decrypt ? K_r0[20] : K_r0[41]; +assign K2[17] = decrypt ? K_r0[3] : K_r0[24]; +assign K2[18] = decrypt ? K_r0[48] : K_r0[12]; +assign K2[19] = decrypt ? K_r0[47] : K_r0[11]; +assign K2[20] = decrypt ? K_r0[41] : K_r0[5]; +assign K2[21] = decrypt ? K_r0[10] : K_r0[6]; +assign K2[22] = decrypt ? K_r0[18] : K_r0[39]; +assign K2[23] = decrypt ? K_r0[26] : K_r0[47]; +assign K2[24] = decrypt ? K_r0[6] : K_r0[27]; +assign K2[25] = decrypt ? K_r0[22] : K_r0[43]; +assign K2[26] = decrypt ? K_r0[44] : K_r0[38]; +assign K2[27] = decrypt ? K_r0[7] : K_r0[28]; +assign K2[28] = decrypt ? K_r0[49] : K_r0[15]; +assign K2[29] = decrypt ? K_r0[9] : K_r0[30]; +assign K2[30] = decrypt ? K_r0[38] : K_r0[0]; +assign K2[31] = decrypt ? K_r0[0] : K_r0[21]; +assign K2[32] = decrypt ? K_r0[15] : K_r0[36]; +assign K2[33] = decrypt ? K_r0[37] : K_r0[31]; +assign K2[34] = decrypt ? K_r0[50] : K_r0[16]; +assign K2[35] = decrypt ? K_r0[21] : K_r0[42]; +assign K2[36] = decrypt ? K_r0[16] : K_r0[37]; +assign K2[37] = decrypt ? K_r0[43] : K_r0[9]; +assign K2[38] = decrypt ? K_r0[23] : K_r0[44]; +assign K2[39] = decrypt ? K_r0[8] : K_r0[29]; +assign K2[40] = decrypt ? K_r0[45] : K_r0[7]; +assign K2[41] = decrypt ? K_r0[28] : K_r0[49]; +assign K2[42] = decrypt ? K_r0[51] : K_r0[45]; +assign K2[43] = decrypt ? K_r0[2] : K_r0[23]; +assign K2[44] = decrypt ? K_r0[29] : K_r0[50]; +assign K2[45] = decrypt ? K_r0[30] : K_r0[51]; +assign K2[46] = decrypt ? K_r0[42] : K_r0[8]; +assign K2[47] = decrypt ? K_r0[52] : K_r0[14]; +assign K2[48] = decrypt ? K_r0[14] : K_r0[35]; + +assign K1[1] = decrypt ? K[40] : K[47]; +assign K1[2] = decrypt ? K[4] : K[11]; +assign K1[3] = decrypt ? K[19] : K[26]; +assign K1[4] = decrypt ? K[53] : K[3]; +assign K1[5] = decrypt ? K[6] : K[13]; +assign K1[6] = decrypt ? K[34] : K[41]; +assign K1[7] = decrypt ? K[20] : K[27]; +assign K1[8] = decrypt ? K[24] : K[6]; +assign K1[9] = decrypt ? K[47] : K[54]; +assign K1[10] = decrypt ? K[41] : K[48]; +assign K1[11] = decrypt ? K[32] : K[39]; +assign K1[12] = decrypt ? K[12] : K[19]; +assign K1[13] = decrypt ? K[46] : K[53]; +assign K1[14] = decrypt ? K[18] : K[25]; +assign K1[15] = decrypt ? K[26] : K[33]; +assign K1[16] = decrypt ? K[27] : K[34]; +assign K1[17] = decrypt ? K[10] : K[17]; +assign K1[18] = decrypt ? K[55] : K[5]; +assign K1[19] = decrypt ? K[54] : K[4]; +assign K1[20] = decrypt ? K[48] : K[55]; +assign K1[21] = decrypt ? K[17] : K[24]; +assign K1[22] = decrypt ? K[25] : K[32]; +assign K1[23] = decrypt ? K[33] : K[40]; +assign K1[24] = decrypt ? K[13] : K[20]; +assign K1[25] = decrypt ? K[29] : K[36]; +assign K1[26] = decrypt ? K[51] : K[31]; +assign K1[27] = decrypt ? K[14] : K[21]; +assign K1[28] = decrypt ? K[1] : K[8]; +assign K1[29] = decrypt ? K[16] : K[23]; +assign K1[30] = decrypt ? K[45] : K[52]; +assign K1[31] = decrypt ? K[7] : K[14]; +assign K1[32] = decrypt ? K[22] : K[29]; +assign K1[33] = decrypt ? K[44] : K[51]; +assign K1[34] = decrypt ? K[2] : K[9]; +assign K1[35] = decrypt ? K[28] : K[35]; +assign K1[36] = decrypt ? K[23] : K[30]; +assign K1[37] = decrypt ? K[50] : K[2]; +assign K1[38] = decrypt ? K[30] : K[37]; +assign K1[39] = decrypt ? K[15] : K[22]; +assign K1[40] = decrypt ? K[52] : K[0]; +assign K1[41] = decrypt ? K[35] : K[42]; +assign K1[42] = decrypt ? K[31] : K[38]; +assign K1[43] = decrypt ? K[9] : K[16]; +assign K1[44] = decrypt ? K[36] : K[43]; +assign K1[45] = decrypt ? K[37] : K[44]; +assign K1[46] = decrypt ? K[49] : K[1]; +assign K1[47] = decrypt ? K[0] : K[7]; +assign K1[48] = decrypt ? K[21] : K[28]; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v new file mode 100644 index 000000000..c967d6f93 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v @@ -0,0 +1,134 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_clockgen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_clockgen.v,v $ +// Revision 1.4 2005/02/21 12:48:05 igorm +// Warning fixes. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:55 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`include "timescale.v" + +module eth_clockgen(Clk, Reset, Divider, MdcEn, MdcEn_n, Mdc); + +parameter Tp=1; + +input Clk; // Input clock (Host clock) +input Reset; // Reset signal +input [7:0] Divider; // Divider (input clock will be divided by the Divider[7:0]) + +output Mdc; // Output clock +output MdcEn; // Enable signal is asserted for one Clk period before Mdc rises. +output MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. + +reg Mdc; +reg [7:0] Counter; + +wire CountEq0; +wire [7:0] CounterPreset; +wire [7:0] TempDivider; + + +assign TempDivider[7:0] = (Divider[7:0]<2)? 8'h02 : Divider[7:0]; // If smaller than 2 +assign CounterPreset[7:0] = (TempDivider[7:0]>>1) - 1'b1; // We are counting half of period + + +// Counter counts half period +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Counter[7:0] <= #Tp 8'h1; + else + begin + if(CountEq0) + begin + Counter[7:0] <= #Tp CounterPreset[7:0]; + end + else + Counter[7:0] <= #Tp Counter - 8'h1; + end +end + + +// Mdc is asserted every other half period +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Mdc <= #Tp 1'b0; + else + begin + if(CountEq0) + Mdc <= #Tp ~Mdc; + end +end + + +assign CountEq0 = Counter == 8'h0; +assign MdcEn = CountEq0 & ~Mdc; +assign MdcEn_n = CountEq0 & Mdc; + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v new file mode 100644 index 000000000..b2eff1b20 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v @@ -0,0 +1,392 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_cop.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_cop.v,v $ +// Revision 1.4 2003/06/13 11:55:37 mohor +// Define file in eth_cop.v is changed to eth_defines.v. Some defines were +// moved from tb_eth_defines.v to eth_defines.v. +// +// Revision 1.3 2002/10/10 16:43:59 mohor +// Minor $display change. +// +// Revision 1.2 2002/09/09 12:54:13 mohor +// error acknowledge cycle termination added to display. +// +// Revision 1.1 2002/08/14 17:16:07 mohor +// Traffic cop with 2 wishbone master interfaces and 2 wishbona slave +// interfaces: +// - Host connects to the master interface +// - Ethernet master (DMA) connects to the second master interface +// - Memory interface connects to the slave interface +// - Ethernet slave interface (access to registers and BDs) connects to second +// slave interface +// +// +// +// +// + +`include "eth_defines.v" +`include "timescale.v" + +module eth_cop +( + // WISHBONE common + wb_clk_i, wb_rst_i, + + // WISHBONE MASTER 1 + m1_wb_adr_i, m1_wb_sel_i, m1_wb_we_i, m1_wb_dat_o, + m1_wb_dat_i, m1_wb_cyc_i, m1_wb_stb_i, m1_wb_ack_o, + m1_wb_err_o, + + // WISHBONE MASTER 2 + m2_wb_adr_i, m2_wb_sel_i, m2_wb_we_i, m2_wb_dat_o, + m2_wb_dat_i, m2_wb_cyc_i, m2_wb_stb_i, m2_wb_ack_o, + m2_wb_err_o, + + // WISHBONE slave 1 + s1_wb_adr_o, s1_wb_sel_o, s1_wb_we_o, s1_wb_cyc_o, + s1_wb_stb_o, s1_wb_ack_i, s1_wb_err_i, s1_wb_dat_i, + s1_wb_dat_o, + + // WISHBONE slave 2 + s2_wb_adr_o, s2_wb_sel_o, s2_wb_we_o, s2_wb_cyc_o, + s2_wb_stb_o, s2_wb_ack_i, s2_wb_err_i, s2_wb_dat_i, + s2_wb_dat_o +); + +parameter Tp=1; + +// WISHBONE common +input wb_clk_i, wb_rst_i; + +// WISHBONE MASTER 1 +input [31:0] m1_wb_adr_i, m1_wb_dat_i; +input [3:0] m1_wb_sel_i; +input m1_wb_cyc_i, m1_wb_stb_i, m1_wb_we_i; +output [31:0] m1_wb_dat_o; +output m1_wb_ack_o, m1_wb_err_o; + +// WISHBONE MASTER 2 +input [31:0] m2_wb_adr_i, m2_wb_dat_i; +input [3:0] m2_wb_sel_i; +input m2_wb_cyc_i, m2_wb_stb_i, m2_wb_we_i; +output [31:0] m2_wb_dat_o; +output m2_wb_ack_o, m2_wb_err_o; + +// WISHBONE slave 1 +input [31:0] s1_wb_dat_i; +input s1_wb_ack_i, s1_wb_err_i; +output [31:0] s1_wb_adr_o, s1_wb_dat_o; +output [3:0] s1_wb_sel_o; +output s1_wb_we_o, s1_wb_cyc_o, s1_wb_stb_o; + +// WISHBONE slave 2 +input [31:0] s2_wb_dat_i; +input s2_wb_ack_i, s2_wb_err_i; +output [31:0] s2_wb_adr_o, s2_wb_dat_o; +output [3:0] s2_wb_sel_o; +output s2_wb_we_o, s2_wb_cyc_o, s2_wb_stb_o; + +reg m1_in_progress; +reg m2_in_progress; +reg [31:0] s1_wb_adr_o; +reg [3:0] s1_wb_sel_o; +reg s1_wb_we_o; +reg [31:0] s1_wb_dat_o; +reg s1_wb_cyc_o; +reg s1_wb_stb_o; +reg [31:0] s2_wb_adr_o; +reg [3:0] s2_wb_sel_o; +reg s2_wb_we_o; +reg [31:0] s2_wb_dat_o; +reg s2_wb_cyc_o; +reg s2_wb_stb_o; + +reg m1_wb_ack_o; +reg [31:0] m1_wb_dat_o; +reg m2_wb_ack_o; +reg [31:0] m2_wb_dat_o; + +reg m1_wb_err_o; +reg m2_wb_err_o; + +wire m_wb_access_finished; +wire m1_req = m1_wb_cyc_i & m1_wb_stb_i & (`M1_ADDRESSED_S1 | `M1_ADDRESSED_S2); +wire m2_req = m2_wb_cyc_i & m2_wb_stb_i & (`M2_ADDRESSED_S1 | `M2_ADDRESSED_S2); + +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + m1_in_progress <=#Tp 0; + m2_in_progress <=#Tp 0; + s1_wb_adr_o <=#Tp 0; + s1_wb_sel_o <=#Tp 0; + s1_wb_we_o <=#Tp 0; + s1_wb_dat_o <=#Tp 0; + s1_wb_cyc_o <=#Tp 0; + s1_wb_stb_o <=#Tp 0; + s2_wb_adr_o <=#Tp 0; + s2_wb_sel_o <=#Tp 0; + s2_wb_we_o <=#Tp 0; + s2_wb_dat_o <=#Tp 0; + s2_wb_cyc_o <=#Tp 0; + s2_wb_stb_o <=#Tp 0; + end + else + begin + case({m1_in_progress, m2_in_progress, m1_req, m2_req, m_wb_access_finished}) // synopsys_full_case synopsys_paralel_case + 5'b00_10_0, 5'b00_11_0 : + begin + m1_in_progress <=#Tp 1'b1; // idle: m1 or (m1 & m2) want access: m1 -> m + if(`M1_ADDRESSED_S1) + begin + s1_wb_adr_o <=#Tp m1_wb_adr_i; + s1_wb_sel_o <=#Tp m1_wb_sel_i; + s1_wb_we_o <=#Tp m1_wb_we_i; + s1_wb_dat_o <=#Tp m1_wb_dat_i; + s1_wb_cyc_o <=#Tp 1'b1; + s1_wb_stb_o <=#Tp 1'b1; + end + else if(`M1_ADDRESSED_S2) + begin + s2_wb_adr_o <=#Tp m1_wb_adr_i; + s2_wb_sel_o <=#Tp m1_wb_sel_i; + s2_wb_we_o <=#Tp m1_wb_we_i; + s2_wb_dat_o <=#Tp m1_wb_dat_i; + s2_wb_cyc_o <=#Tp 1'b1; + s2_wb_stb_o <=#Tp 1'b1; + end + else + $display("(%t)(%m)WISHBONE ERROR: Unspecified address space accessed", $time); + end + 5'b00_01_0 : + begin + m2_in_progress <=#Tp 1'b1; // idle: m2 wants access: m2 -> m + if(`M2_ADDRESSED_S1) + begin + s1_wb_adr_o <=#Tp m2_wb_adr_i; + s1_wb_sel_o <=#Tp m2_wb_sel_i; + s1_wb_we_o <=#Tp m2_wb_we_i; + s1_wb_dat_o <=#Tp m2_wb_dat_i; + s1_wb_cyc_o <=#Tp 1'b1; + s1_wb_stb_o <=#Tp 1'b1; + end + else if(`M2_ADDRESSED_S2) + begin + s2_wb_adr_o <=#Tp m2_wb_adr_i; + s2_wb_sel_o <=#Tp m2_wb_sel_i; + s2_wb_we_o <=#Tp m2_wb_we_i; + s2_wb_dat_o <=#Tp m2_wb_dat_i; + s2_wb_cyc_o <=#Tp 1'b1; + s2_wb_stb_o <=#Tp 1'b1; + end + else + $display("(%t)(%m)WISHBONE ERROR: Unspecified address space accessed", $time); + end + 5'b10_10_1, 5'b10_11_1 : + begin + m1_in_progress <=#Tp 1'b0; // m1 in progress. Cycle is finished. Send ack or err to m1. + if(`M1_ADDRESSED_S1) + begin + s1_wb_cyc_o <=#Tp 1'b0; + s1_wb_stb_o <=#Tp 1'b0; + end + else if(`M1_ADDRESSED_S2) + begin + s2_wb_cyc_o <=#Tp 1'b0; + s2_wb_stb_o <=#Tp 1'b0; + end + end + 5'b01_01_1, 5'b01_11_1 : + begin + m2_in_progress <=#Tp 1'b0; // m2 in progress. Cycle is finished. Send ack or err to m2. + if(`M2_ADDRESSED_S1) + begin + s1_wb_cyc_o <=#Tp 1'b0; + s1_wb_stb_o <=#Tp 1'b0; + end + else if(`M2_ADDRESSED_S2) + begin + s2_wb_cyc_o <=#Tp 1'b0; + s2_wb_stb_o <=#Tp 1'b0; + end + end + endcase + end +end + +// Generating Ack for master 1 +always @ (m1_in_progress or m1_wb_adr_i or s1_wb_ack_i or s2_wb_ack_i or s1_wb_dat_i or s2_wb_dat_i or `M1_ADDRESSED_S1 or `M1_ADDRESSED_S2) +begin + if(m1_in_progress) + begin + if(`M1_ADDRESSED_S1) begin + m1_wb_ack_o <= s1_wb_ack_i; + m1_wb_dat_o <= s1_wb_dat_i; + end + else if(`M1_ADDRESSED_S2) begin + m1_wb_ack_o <= s2_wb_ack_i; + m1_wb_dat_o <= s2_wb_dat_i; + end + end + else + m1_wb_ack_o <= 0; +end + + +// Generating Ack for master 2 +always @ (m2_in_progress or m2_wb_adr_i or s1_wb_ack_i or s2_wb_ack_i or s1_wb_dat_i or s2_wb_dat_i or `M2_ADDRESSED_S1 or `M2_ADDRESSED_S2) +begin + if(m2_in_progress) + begin + if(`M2_ADDRESSED_S1) begin + m2_wb_ack_o <= s1_wb_ack_i; + m2_wb_dat_o <= s1_wb_dat_i; + end + else if(`M2_ADDRESSED_S2) begin + m2_wb_ack_o <= s2_wb_ack_i; + m2_wb_dat_o <= s2_wb_dat_i; + end + end + else + m2_wb_ack_o <= 0; +end + + +// Generating Err for master 1 +always @ (m1_in_progress or m1_wb_adr_i or s1_wb_err_i or s2_wb_err_i or `M2_ADDRESSED_S1 or `M2_ADDRESSED_S2 or + m1_wb_cyc_i or m1_wb_stb_i) +begin + if(m1_in_progress) begin + if(`M1_ADDRESSED_S1) + m1_wb_err_o <= s1_wb_err_i; + else if(`M1_ADDRESSED_S2) + m1_wb_err_o <= s2_wb_err_i; + end + else if(m1_wb_cyc_i & m1_wb_stb_i & ~`M1_ADDRESSED_S1 & ~`M1_ADDRESSED_S2) + m1_wb_err_o <= 1'b1; + else + m1_wb_err_o <= 1'b0; +end + + +// Generating Err for master 2 +always @ (m2_in_progress or m2_wb_adr_i or s1_wb_err_i or s2_wb_err_i or `M2_ADDRESSED_S1 or `M2_ADDRESSED_S2 or + m2_wb_cyc_i or m2_wb_stb_i) +begin + if(m2_in_progress) begin + if(`M2_ADDRESSED_S1) + m2_wb_err_o <= s1_wb_err_i; + else if(`M2_ADDRESSED_S2) + m2_wb_err_o <= s2_wb_err_i; + end + else if(m2_wb_cyc_i & m2_wb_stb_i & ~`M2_ADDRESSED_S1 & ~`M2_ADDRESSED_S2) + m2_wb_err_o <= 1'b1; + else + m2_wb_err_o <= 1'b0; +end + + +assign m_wb_access_finished = m1_wb_ack_o | m1_wb_err_o | m2_wb_ack_o | m2_wb_err_o; + + +// Activity monitor +integer cnt; +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + cnt <=#Tp 0; + else + if(s1_wb_ack_i | s1_wb_err_i | s2_wb_ack_i | s2_wb_err_i) + cnt <=#Tp 0; + else + if(s1_wb_cyc_o | s2_wb_cyc_o) + cnt <=#Tp cnt+1; +end + +always @ (posedge wb_clk_i) +begin + if(cnt==1000) begin + $display("(%0t)(%m) ERROR: WB activity ??? ", $time); + if(s1_wb_cyc_o) begin + $display("s1_wb_dat_o = 0x%0x", s1_wb_dat_o); + $display("s1_wb_adr_o = 0x%0x", s1_wb_adr_o); + $display("s1_wb_sel_o = 0x%0x", s1_wb_sel_o); + $display("s1_wb_we_o = 0x%0x", s1_wb_we_o); + end + else if(s2_wb_cyc_o) begin + $display("s2_wb_dat_o = 0x%0x", s2_wb_dat_o); + $display("s2_wb_adr_o = 0x%0x", s2_wb_adr_o); + $display("s2_wb_sel_o = 0x%0x", s2_wb_sel_o); + $display("s2_wb_we_o = 0x%0x", s2_wb_we_o); + end + + $stop; + end +end + + +always @ (posedge wb_clk_i) +begin + if(s1_wb_err_i & s1_wb_cyc_o) begin + $display("(%0t) ERROR: WB cycle finished with error acknowledge ", $time); + $display("s1_wb_dat_o = 0x%0x", s1_wb_dat_o); + $display("s1_wb_adr_o = 0x%0x", s1_wb_adr_o); + $display("s1_wb_sel_o = 0x%0x", s1_wb_sel_o); + $display("s1_wb_we_o = 0x%0x", s1_wb_we_o); + $stop; + end + if(s2_wb_err_i & s2_wb_cyc_o) begin + $display("(%0t) ERROR: WB cycle finished with error acknowledge ", $time); + $display("s2_wb_dat_o = 0x%0x", s2_wb_dat_o); + $display("s2_wb_adr_o = 0x%0x", s2_wb_adr_o); + $display("s2_wb_sel_o = 0x%0x", s2_wb_sel_o); + $display("s2_wb_we_o = 0x%0x", s2_wb_we_o); + $stop; + end +end + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v new file mode 100644 index 000000000..5fe30503a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v @@ -0,0 +1,148 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_crc.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_crc.v,v $ +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/19 18:16:40 mohor +// TxClk changed to MTxClk (as discribed in the documentation). +// Crc changed so only one file can be used instead of two. +// +// Revision 1.2 2001/06/19 10:38:07 mohor +// Minor changes in header. +// +// Revision 1.1 2001/06/19 10:27:57 mohor +// TxEthMAC initial release. +// +// +// + + +`include "timescale.v" + +module eth_crc (Clk, Reset, Data, Enable, Initialize, Crc, CrcError); + + +parameter Tp = 1; + +input Clk; +input Reset; +input [3:0] Data; +input Enable; +input Initialize; + +output [31:0] Crc; +output CrcError; + +reg [31:0] Crc; + +wire [31:0] CrcNext; + + +assign CrcNext[0] = Enable & (Data[0] ^ Crc[28]); +assign CrcNext[1] = Enable & (Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29]); +assign CrcNext[2] = Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30]); +assign CrcNext[3] = Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31]); +assign CrcNext[4] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[0]; +assign CrcNext[5] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[1]; +assign CrcNext[6] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[ 2]; +assign CrcNext[7] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[3]; +assign CrcNext[8] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[4]; +assign CrcNext[9] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[5]; +assign CrcNext[10] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[6]; +assign CrcNext[11] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[7]; +assign CrcNext[12] = (Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30])) ^ Crc[8]; +assign CrcNext[13] = (Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31])) ^ Crc[9]; +assign CrcNext[14] = (Enable & (Data[3] ^ Data[2] ^ Crc[30] ^ Crc[31])) ^ Crc[10]; +assign CrcNext[15] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[11]; +assign CrcNext[16] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[12]; +assign CrcNext[17] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[13]; +assign CrcNext[18] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[14]; +assign CrcNext[19] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[15]; +assign CrcNext[20] = Crc[16]; +assign CrcNext[21] = Crc[17]; +assign CrcNext[22] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[18]; +assign CrcNext[23] = (Enable & (Data[1] ^ Data[0] ^ Crc[29] ^ Crc[28])) ^ Crc[19]; +assign CrcNext[24] = (Enable & (Data[2] ^ Data[1] ^ Crc[30] ^ Crc[29])) ^ Crc[20]; +assign CrcNext[25] = (Enable & (Data[3] ^ Data[2] ^ Crc[31] ^ Crc[30])) ^ Crc[21]; +assign CrcNext[26] = (Enable & (Data[3] ^ Data[0] ^ Crc[31] ^ Crc[28])) ^ Crc[22]; +assign CrcNext[27] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[23]; +assign CrcNext[28] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[24]; +assign CrcNext[29] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[25]; +assign CrcNext[30] = Crc[26]; +assign CrcNext[31] = Crc[27]; + + +always @ (posedge Clk or posedge Reset) +begin + if (Reset) + Crc <= #1 32'hffffffff; + else + if(Initialize) + Crc <= #Tp 32'hffffffff; + else + Crc <= #Tp CrcNext; +end + +assign CrcError = Crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v new file mode 100644 index 000000000..b2d593d99 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v @@ -0,0 +1,348 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_defines.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_defines.v,v $ +// Revision 1.34 2005/02/21 12:48:06 igorm +// Warning fixes. +// +// Revision 1.33 2003/11/12 18:24:58 tadejm +// WISHBONE slave changed and tested from only 32-bit accesss to byte access. +// +// Revision 1.32 2003/10/17 07:46:13 markom +// mbist signals updated according to newest convention +// +// Revision 1.31 2003/08/14 16:42:58 simons +// Artisan ram instance added. +// +// Revision 1.30 2003/06/13 11:55:37 mohor +// Define file in eth_cop.v is changed to eth_defines.v. Some defines were +// moved from tb_eth_defines.v to eth_defines.v. +// +// Revision 1.29 2002/11/19 18:13:49 mohor +// r_MiiMRst is not used for resetting the MIIM module. wb_rst used instead. +// +// Revision 1.28 2002/11/15 14:27:15 mohor +// Since r_Rst bit is not used any more, default value is changed to 0xa000. +// +// Revision 1.27 2002/11/01 18:19:34 mohor +// Defines fixed to use generic RAM by default. +// +// Revision 1.26 2002/10/24 18:53:03 mohor +// fpga define added. +// +// Revision 1.3 2002/10/11 16:57:54 igorm +// eth_defines.v tagged with rel_5 used. +// +// Revision 1.25 2002/10/10 16:47:44 mohor +// Defines changed to have ETH_ prolog. +// ETH_WISHBONE_B# define added. +// +// Revision 1.24 2002/10/10 16:33:11 mohor +// Bist added. +// +// Revision 1.23 2002/09/23 18:22:48 mohor +// Virtual Silicon RAM might be used in the ASIC implementation of the ethernet +// core. +// +// Revision 1.22 2002/09/04 18:36:49 mohor +// Defines for control registers added (ETH_TXCTRL and ETH_RXCTRL). +// +// Revision 1.21 2002/08/16 22:09:47 mohor +// Defines for register width added. mii_rst signal in MIIMODER register +// changed. +// +// Revision 1.20 2002/08/14 19:31:48 mohor +// Register TX_BD_NUM is changed so it contains value of the Tx buffer descriptors. No +// need to multiply or devide any more. +// +// Revision 1.19 2002/07/23 15:28:31 mohor +// Ram , used for BDs changed from generic_spram to eth_spram_256x32. +// +// Revision 1.18 2002/05/03 10:15:50 mohor +// Outputs registered. Reset changed for eth_wishbone module. +// +// Revision 1.17 2002/04/24 08:52:19 mohor +// Compiler directives added. Tx and Rx fifo size incremented. A "late collision" +// bug fixed. +// +// Revision 1.16 2002/03/19 12:53:29 mohor +// Some defines that are used in testbench only were moved to tb_eth_defines.v +// file. +// +// Revision 1.15 2002/02/26 16:11:32 mohor +// Number of interrupts changed +// +// Revision 1.14 2002/02/16 14:03:44 mohor +// Registered trimmed. Unused registers removed. +// +// Revision 1.13 2002/02/16 13:06:33 mohor +// EXTERNAL_DMA used instead of WISHBONE_DMA. +// +// Revision 1.12 2002/02/15 10:58:31 mohor +// Changed that were lost with last update put back to the file. +// +// Revision 1.11 2002/02/14 20:19:41 billditt +// Modified for Address Checking, +// addition of eth_addrcheck.v +// +// Revision 1.10 2002/02/12 17:01:19 mohor +// HASH0 and HASH1 registers added. + +// Revision 1.9 2002/02/08 16:21:54 mohor +// Rx status is written back to the BD. +// +// Revision 1.8 2002/02/05 16:44:38 mohor +// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200 +// MHz. Statuses, overrun, control frame transmission and reception still need +// to be fixed. +// +// Revision 1.7 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.6 2001/12/05 15:00:16 mohor +// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors +// instead of the number of RX descriptors). +// +// Revision 1.5 2001/12/05 10:21:37 mohor +// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead. +// +// Revision 1.4 2001/11/13 14:23:56 mohor +// Generic memory model is used. Defines are changed for the same reason. +// +// Revision 1.3 2001/10/18 12:07:11 mohor +// Status signals changed, Adress decoding changed, interrupt controller +// added. +// +// Revision 1.2 2001/09/24 15:02:56 mohor +// Defines changed (All precede with ETH_). Small changes because some +// tools generate warnings when two operands are together. Synchronization +// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC +// demands). +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// +// +// +// + + + +//`define ETH_BIST // Bist for usage with Virtual Silicon RAMS + +`define ETH_MBIST_CTRL_WIDTH 3 // width of MBIST control bus + +// Ethernet implemented in Xilinx Chips (uncomment following lines) +// `define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo +// `define ETH_XILINX_RAMB4 // Selection of the used memory for Buffer descriptors + // Core is going to be implemented in Virtex FPGA and contains Virtex + // specific elements. + +// Ethernet implemented in Altera Chips (uncomment following lines) +//`define ETH_ALTERA_ALTSYNCRAM + +// Ethernet implemented in ASIC with Virtual Silicon RAMs +// `define ETH_VIRTUAL_SILICON_RAM // Virtual Silicon RAMS used storing buffer decriptors (ASIC implementation) + +// Ethernet implemented in ASIC with Artisan RAMs +// `define ETH_ARTISAN_RAM // Artisan RAMS used storing buffer decriptors (ASIC implementation) + +// Uncomment when Avalon bus is used +//`define ETH_AVALON_BUS + +`define ETH_MODER_ADR 8'h0 // 0x0 +`define ETH_INT_SOURCE_ADR 8'h1 // 0x4 +`define ETH_INT_MASK_ADR 8'h2 // 0x8 +`define ETH_IPGT_ADR 8'h3 // 0xC +`define ETH_IPGR1_ADR 8'h4 // 0x10 +`define ETH_IPGR2_ADR 8'h5 // 0x14 +`define ETH_PACKETLEN_ADR 8'h6 // 0x18 +`define ETH_COLLCONF_ADR 8'h7 // 0x1C +`define ETH_TX_BD_NUM_ADR 8'h8 // 0x20 +`define ETH_CTRLMODER_ADR 8'h9 // 0x24 +`define ETH_MIIMODER_ADR 8'hA // 0x28 +`define ETH_MIICOMMAND_ADR 8'hB // 0x2C +`define ETH_MIIADDRESS_ADR 8'hC // 0x30 +`define ETH_MIITX_DATA_ADR 8'hD // 0x34 +`define ETH_MIIRX_DATA_ADR 8'hE // 0x38 +`define ETH_MIISTATUS_ADR 8'hF // 0x3C +`define ETH_MAC_ADDR0_ADR 8'h10 // 0x40 +`define ETH_MAC_ADDR1_ADR 8'h11 // 0x44 +`define ETH_HASH0_ADR 8'h12 // 0x48 +`define ETH_HASH1_ADR 8'h13 // 0x4C +`define ETH_TX_CTRL_ADR 8'h14 // 0x50 +`define ETH_RX_CTRL_ADR 8'h15 // 0x54 + + +`define ETH_MODER_DEF_0 8'h00 +`define ETH_MODER_DEF_1 8'hA0 +`define ETH_MODER_DEF_2 1'h0 +`define ETH_INT_MASK_DEF_0 7'h0 +`define ETH_IPGT_DEF_0 7'h12 +`define ETH_IPGR1_DEF_0 7'h0C +`define ETH_IPGR2_DEF_0 7'h12 +`define ETH_PACKETLEN_DEF_0 8'h00 +`define ETH_PACKETLEN_DEF_1 8'h06 +`define ETH_PACKETLEN_DEF_2 8'h40 +`define ETH_PACKETLEN_DEF_3 8'h00 +`define ETH_COLLCONF_DEF_0 6'h3f +`define ETH_COLLCONF_DEF_2 4'hF +`define ETH_TX_BD_NUM_DEF_0 8'h40 +`define ETH_CTRLMODER_DEF_0 3'h0 +`define ETH_MIIMODER_DEF_0 8'h64 +`define ETH_MIIMODER_DEF_1 1'h0 +`define ETH_MIIADDRESS_DEF_0 5'h00 +`define ETH_MIIADDRESS_DEF_1 5'h00 +`define ETH_MIITX_DATA_DEF_0 8'h00 +`define ETH_MIITX_DATA_DEF_1 8'h00 +`define ETH_MIIRX_DATA_DEF 16'h0000 // not written from WB +`define ETH_MAC_ADDR0_DEF_0 8'h00 +`define ETH_MAC_ADDR0_DEF_1 8'h00 +`define ETH_MAC_ADDR0_DEF_2 8'h00 +`define ETH_MAC_ADDR0_DEF_3 8'h00 +`define ETH_MAC_ADDR1_DEF_0 8'h00 +`define ETH_MAC_ADDR1_DEF_1 8'h00 +`define ETH_HASH0_DEF_0 8'h00 +`define ETH_HASH0_DEF_1 8'h00 +`define ETH_HASH0_DEF_2 8'h00 +`define ETH_HASH0_DEF_3 8'h00 +`define ETH_HASH1_DEF_0 8'h00 +`define ETH_HASH1_DEF_1 8'h00 +`define ETH_HASH1_DEF_2 8'h00 +`define ETH_HASH1_DEF_3 8'h00 +`define ETH_TX_CTRL_DEF_0 8'h00 // +`define ETH_TX_CTRL_DEF_1 8'h00 // +`define ETH_TX_CTRL_DEF_2 1'h0 // +`define ETH_RX_CTRL_DEF_0 8'h00 +`define ETH_RX_CTRL_DEF_1 8'h00 + + +`define ETH_MODER_WIDTH_0 8 +`define ETH_MODER_WIDTH_1 8 +`define ETH_MODER_WIDTH_2 1 +`define ETH_INT_SOURCE_WIDTH_0 7 +`define ETH_INT_MASK_WIDTH_0 7 +`define ETH_IPGT_WIDTH_0 7 +`define ETH_IPGR1_WIDTH_0 7 +`define ETH_IPGR2_WIDTH_0 7 +`define ETH_PACKETLEN_WIDTH_0 8 +`define ETH_PACKETLEN_WIDTH_1 8 +`define ETH_PACKETLEN_WIDTH_2 8 +`define ETH_PACKETLEN_WIDTH_3 8 +`define ETH_COLLCONF_WIDTH_0 6 +`define ETH_COLLCONF_WIDTH_2 4 +`define ETH_TX_BD_NUM_WIDTH_0 8 +`define ETH_CTRLMODER_WIDTH_0 3 +`define ETH_MIIMODER_WIDTH_0 8 +`define ETH_MIIMODER_WIDTH_1 1 +`define ETH_MIICOMMAND_WIDTH_0 3 +`define ETH_MIIADDRESS_WIDTH_0 5 +`define ETH_MIIADDRESS_WIDTH_1 5 +`define ETH_MIITX_DATA_WIDTH_0 8 +`define ETH_MIITX_DATA_WIDTH_1 8 +`define ETH_MIIRX_DATA_WIDTH 16 // not written from WB +`define ETH_MIISTATUS_WIDTH 3 // not written from WB +`define ETH_MAC_ADDR0_WIDTH_0 8 +`define ETH_MAC_ADDR0_WIDTH_1 8 +`define ETH_MAC_ADDR0_WIDTH_2 8 +`define ETH_MAC_ADDR0_WIDTH_3 8 +`define ETH_MAC_ADDR1_WIDTH_0 8 +`define ETH_MAC_ADDR1_WIDTH_1 8 +`define ETH_HASH0_WIDTH_0 8 +`define ETH_HASH0_WIDTH_1 8 +`define ETH_HASH0_WIDTH_2 8 +`define ETH_HASH0_WIDTH_3 8 +`define ETH_HASH1_WIDTH_0 8 +`define ETH_HASH1_WIDTH_1 8 +`define ETH_HASH1_WIDTH_2 8 +`define ETH_HASH1_WIDTH_3 8 +`define ETH_TX_CTRL_WIDTH_0 8 +`define ETH_TX_CTRL_WIDTH_1 8 +`define ETH_TX_CTRL_WIDTH_2 1 +`define ETH_RX_CTRL_WIDTH_0 8 +`define ETH_RX_CTRL_WIDTH_1 8 + + +// Outputs are registered (uncomment when needed) +`define ETH_REGISTERED_OUTPUTS + +// Settings for TX FIFO +`define ETH_TX_FIFO_CNT_WIDTH 5 +`define ETH_TX_FIFO_DEPTH 16 +`define ETH_TX_FIFO_DATA_WIDTH 32 + +// Settings for RX FIFO +`define ETH_RX_FIFO_CNT_WIDTH 5 +`define ETH_RX_FIFO_DEPTH 16 +`define ETH_RX_FIFO_DATA_WIDTH 32 + +// Burst length +`define ETH_BURST_LENGTH 4 // Change also ETH_BURST_CNT_WIDTH +`define ETH_BURST_CNT_WIDTH 3 // The counter must be width enough to count to ETH_BURST_LENGTH + +// WISHBONE interface is Revision B3 compliant (uncomment when needed) +//`define ETH_WISHBONE_B3 + + +// Following defines are needed when eth_cop.v is used. Otherwise they may be deleted. +`define ETH_BASE 32'hd0000000 +`define ETH_WIDTH 32'h800 +`define MEMORY_BASE 32'h2000 +`define MEMORY_WIDTH 32'h10000 + +`define M1_ADDRESSED_S1 ( (m1_wb_adr_i >= `ETH_BASE) & (m1_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) ) +`define M1_ADDRESSED_S2 ( (m1_wb_adr_i >= `MEMORY_BASE) & (m1_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) ) +`define M2_ADDRESSED_S1 ( (m2_wb_adr_i >= `ETH_BASE) & (m2_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) ) +`define M2_ADDRESSED_S2 ( (m2_wb_adr_i >= `MEMORY_BASE) & (m2_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) ) +// Previous defines are only needed for eth_cop.v + diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v new file mode 100644 index 000000000..8f90a2e36 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v @@ -0,0 +1,189 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_fifo.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_fifo.v,v $ +// Revision 1.4 2005/02/21 12:48:07 igorm +// Warning fixes. +// +// Revision 1.3 2002/04/22 13:45:52 mohor +// Generic ram or Xilinx ram can be used in fifo (selectable by setting +// ETH_FIFO_XILINX in eth_defines.v). +// +// Revision 1.2 2002/03/25 13:33:04 mohor +// When clear and read/write are active at the same time, cnt and pointers are +// set to 1. +// +// Revision 1.1 2002/02/05 16:44:39 mohor +// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200 +// MHz. Statuses, overrun, control frame transmission and reception still need +// to be fixed. +// +// + +`include "eth_defines.v" +`include "timescale.v" + +module eth_fifo (data_in, data_out, clk, reset, write, read, clear, almost_full, full, almost_empty, empty, cnt); + +parameter DATA_WIDTH = 32; +parameter DEPTH = 8; +parameter CNT_WIDTH = 4; + +parameter Tp = 1; + +input clk; +input reset; +input write; +input read; +input clear; +input [DATA_WIDTH-1:0] data_in; + +output [DATA_WIDTH-1:0] data_out; +output almost_full; +output full; +output almost_empty; +output empty; +output [CNT_WIDTH-1:0] cnt; + +`ifdef ETH_FIFO_XILINX +`else + `ifdef ETH_ALTERA_ALTSYNCRAM + `else + reg [DATA_WIDTH-1:0] fifo [0:DEPTH-1]; + reg [DATA_WIDTH-1:0] data_out; + `endif +`endif + +reg [CNT_WIDTH-1:0] cnt; +reg [CNT_WIDTH-2:0] read_pointer; +reg [CNT_WIDTH-2:0] write_pointer; + + +always @ (posedge clk or posedge reset) +begin + if(reset) + cnt <=#Tp 0; + else + if(clear) + cnt <=#Tp { {(CNT_WIDTH-1){1'b0}}, read^write}; + else + if(read ^ write) + if(read) + cnt <=#Tp cnt - 1'b1; + else + cnt <=#Tp cnt + 1'b1; +end + +always @ (posedge clk or posedge reset) +begin + if(reset) + read_pointer <=#Tp 0; + else + if(clear) + read_pointer <=#Tp { {(CNT_WIDTH-2){1'b0}}, read}; + else + if(read & ~empty) + read_pointer <=#Tp read_pointer + 1'b1; +end + +always @ (posedge clk or posedge reset) +begin + if(reset) + write_pointer <=#Tp 0; + else + if(clear) + write_pointer <=#Tp { {(CNT_WIDTH-2){1'b0}}, write}; + else + if(write & ~full) + write_pointer <=#Tp write_pointer + 1'b1; +end + +assign empty = ~(|cnt); +assign almost_empty = cnt == 1; +assign full = cnt == DEPTH; +assign almost_full = &cnt[CNT_WIDTH-2:0]; + + + +`ifdef ETH_FIFO_XILINX + xilinx_dist_ram_16x32 fifo + ( .data_out(data_out), + .we(write & ~full), + .data_in(data_in), + .read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer), + .write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer), + .wclk(clk) + ); +`else // !ETH_FIFO_XILINX +`ifdef ETH_ALTERA_ALTSYNCRAM + altera_dpram_16x32 altera_dpram_16x32_inst + ( + .data (data_in), + .wren (write & ~full), + .wraddress (clear ? {CNT_WIDTH-1{1'b0}} : write_pointer), + .rdaddress (clear ? {CNT_WIDTH-1{1'b0}} : read_pointer ), + .clock (clk), + .q (data_out) + ); //exemplar attribute altera_dpram_16x32_inst NOOPT TRUE +`else // !ETH_ALTERA_ALTSYNCRAM + always @ (posedge clk) + begin + if(write & clear) + fifo[0] <=#Tp data_in; + else + if(write & ~full) + fifo[write_pointer] <=#Tp data_in; + end + + + always @ (posedge clk) + begin + if(clear) + data_out <=#Tp fifo[0]; + else + data_out <=#Tp fifo[read_pointer]; + end +`endif // !ETH_ALTERA_ALTSYNCRAM +`endif // !ETH_FIFO_XILINX + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v new file mode 100644 index 000000000..b93cc1626 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v @@ -0,0 +1,274 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_maccontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_maccontrol.v,v $ +// Revision 1.7 2003/01/22 13:49:26 tadejm +// When control packets were received, they were ignored in some cases. +// +// Revision 1.6 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.5 2002/11/21 00:14:39 mohor +// TxDone and TxAbort changed so they're not propagated to the wishbone +// module when control frame is transmitted. +// +// Revision 1.4 2002/11/19 17:37:32 mohor +// When control frame (PAUSE) was sent, status was written in the +// eth_wishbone module and both TXB and TXC interrupts were set. Fixed. +// Only TXC interrupt is set. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.1 2001/07/03 12:51:54 mohor +// Initial release of the MAC Control module. +// +// +// +// + + +`include "timescale.v" + + +module eth_maccontrol (MTxClk, MRxClk, TxReset, RxReset, TPauseRq, TxDataIn, TxStartFrmIn, TxUsedDataIn, + TxEndFrmIn, TxDoneIn, TxAbortIn, RxData, RxValid, RxStartFrm, RxEndFrm, ReceiveEnd, + ReceivedPacketGood, ReceivedLengthOK, TxFlow, RxFlow, DlyCrcEn, TxPauseTV, + MAC, PadIn, PadOut, CrcEnIn, CrcEnOut, TxDataOut, TxStartFrmOut, TxEndFrmOut, + TxDoneOut, TxAbortOut, TxUsedDataOut, WillSendControlFrame, TxCtrlEndFrm, + ReceivedPauseFrm, ControlFrmAddressOK, SetPauseTimer, r_PassAll, RxStatusWriteLatched_sync2 + ); + + +parameter Tp = 1; + + +input MTxClk; // Transmit clock (from PHY) +input MRxClk; // Receive clock (from PHY) +input TxReset; // Transmit reset +input RxReset; // Receive reset +input TPauseRq; // Transmit control frame (from host) +input [7:0] TxDataIn; // Transmit packet data byte (from host) +input TxStartFrmIn; // Transmit packet start frame input (from host) +input TxUsedDataIn; // Transmit packet used data (from TxEthMAC) +input TxEndFrmIn; // Transmit packet end frame input (from host) +input TxDoneIn; // Transmit packet done (from TxEthMAC) +input TxAbortIn; // Transmit packet abort (input from TxEthMAC) +input PadIn; // Padding (input from registers) +input CrcEnIn; // Crc append (input from registers) +input [7:0] RxData; // Receive Packet Data (from RxEthMAC) +input RxValid; // Received a valid packet +input RxStartFrm; // Receive packet start frame (input from RxEthMAC) +input RxEndFrm; // Receive packet end frame (input from RxEthMAC) +input ReceiveEnd; // End of receiving of the current packet (input from RxEthMAC) +input ReceivedPacketGood; // Received packet is good +input ReceivedLengthOK; // Length of the received packet is OK +input TxFlow; // Tx flow control (from registers) +input RxFlow; // Rx flow control (from registers) +input DlyCrcEn; // Delayed CRC enabled (from registers) +input [15:0] TxPauseTV; // Transmit Pause Timer Value (from registers) +input [47:0] MAC; // MAC address (from registers) +input RxStatusWriteLatched_sync2; +input r_PassAll; + +output [7:0] TxDataOut; // Transmit Packet Data (to TxEthMAC) +output TxStartFrmOut; // Transmit packet start frame (output to TxEthMAC) +output TxEndFrmOut; // Transmit packet end frame (output to TxEthMAC) +output TxDoneOut; // Transmit packet done (to host) +output TxAbortOut; // Transmit packet aborted (to host) +output TxUsedDataOut; // Transmit packet used data (to host) +output PadOut; // Padding (output to TxEthMAC) +output CrcEnOut; // Crc append (output to TxEthMAC) +output WillSendControlFrame; +output TxCtrlEndFrm; +output ReceivedPauseFrm; +output ControlFrmAddressOK; +output SetPauseTimer; + +reg TxUsedDataOutDetected; +reg TxAbortInLatched; +reg TxDoneInLatched; +reg MuxedDone; +reg MuxedAbort; + +wire Pause; +wire TxCtrlStartFrm; +wire [7:0] ControlData; +wire CtrlMux; +wire SendingCtrlFrm; // Sending Control Frame (enables padding and CRC) +wire BlockTxDone; + + +// Signal TxUsedDataOut was detected (a transfer is already in progress) +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + TxUsedDataOutDetected <= #Tp 1'b0; + else + if(TxDoneIn | TxAbortIn) + TxUsedDataOutDetected <= #Tp 1'b0; + else + if(TxUsedDataOut) + TxUsedDataOutDetected <= #Tp 1'b1; +end + + +// Latching variables +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + begin + TxAbortInLatched <= #Tp 1'b0; + TxDoneInLatched <= #Tp 1'b0; + end + else + begin + TxAbortInLatched <= #Tp TxAbortIn; + TxDoneInLatched <= #Tp TxDoneIn; + end +end + + + +// Generating muxed abort signal +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + MuxedAbort <= #Tp 1'b0; + else + if(TxStartFrmIn) + MuxedAbort <= #Tp 1'b0; + else + if(TxAbortIn & ~TxAbortInLatched & TxUsedDataOutDetected) + MuxedAbort <= #Tp 1'b1; +end + + +// Generating muxed done signal +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + MuxedDone <= #Tp 1'b0; + else + if(TxStartFrmIn) + MuxedDone <= #Tp 1'b0; + else + if(TxDoneIn & (~TxDoneInLatched) & TxUsedDataOutDetected) + MuxedDone <= #Tp 1'b1; +end + + +// TxDoneOut +assign TxDoneOut = CtrlMux? ((~TxStartFrmIn) & (~BlockTxDone) & MuxedDone) : + ((~TxStartFrmIn) & (~BlockTxDone) & TxDoneIn); + +// TxAbortOut +assign TxAbortOut = CtrlMux? ((~TxStartFrmIn) & (~BlockTxDone) & MuxedAbort) : + ((~TxStartFrmIn) & (~BlockTxDone) & TxAbortIn); + +// TxUsedDataOut +assign TxUsedDataOut = ~CtrlMux & TxUsedDataIn; + +// TxStartFrmOut +assign TxStartFrmOut = CtrlMux? TxCtrlStartFrm : (TxStartFrmIn & ~Pause); + + +// TxEndFrmOut +assign TxEndFrmOut = CtrlMux? TxCtrlEndFrm : TxEndFrmIn; + + +// TxDataOut[7:0] +assign TxDataOut[7:0] = CtrlMux? ControlData[7:0] : TxDataIn[7:0]; + + +// PadOut +assign PadOut = PadIn | SendingCtrlFrm; + + +// CrcEnOut +assign CrcEnOut = CrcEnIn | SendingCtrlFrm; + + + +// Connecting receivecontrol module +eth_receivecontrol receivecontrol1 +( + .MTxClk(MTxClk), .MRxClk(MRxClk), .TxReset(TxReset), .RxReset(RxReset), .RxData(RxData), + .RxValid(RxValid), .RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm), .RxFlow(RxFlow), + .ReceiveEnd(ReceiveEnd), .MAC(MAC), .DlyCrcEn(DlyCrcEn), .TxDoneIn(TxDoneIn), + .TxAbortIn(TxAbortIn), .TxStartFrmOut(TxStartFrmOut), .ReceivedLengthOK(ReceivedLengthOK), + .ReceivedPacketGood(ReceivedPacketGood), .TxUsedDataOutDetected(TxUsedDataOutDetected), + .Pause(Pause), .ReceivedPauseFrm(ReceivedPauseFrm), .AddressOK(ControlFrmAddressOK), + .r_PassAll(r_PassAll), .RxStatusWriteLatched_sync2(RxStatusWriteLatched_sync2), .SetPauseTimer(SetPauseTimer) +); + + +eth_transmitcontrol transmitcontrol1 +( + .MTxClk(MTxClk), .TxReset(TxReset), .TxUsedDataIn(TxUsedDataIn), .TxUsedDataOut(TxUsedDataOut), + .TxDoneIn(TxDoneIn), .TxAbortIn(TxAbortIn), .TxStartFrmIn(TxStartFrmIn), .TPauseRq(TPauseRq), + .TxUsedDataOutDetected(TxUsedDataOutDetected), .TxFlow(TxFlow), .DlyCrcEn(DlyCrcEn), .TxPauseTV(TxPauseTV), + .MAC(MAC), .TxCtrlStartFrm(TxCtrlStartFrm), .TxCtrlEndFrm(TxCtrlEndFrm), .SendingCtrlFrm(SendingCtrlFrm), + .CtrlMux(CtrlMux), .ControlData(ControlData), .WillSendControlFrame(WillSendControlFrame), .BlockTxDone(BlockTxDone) +); + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v new file mode 100644 index 000000000..bb96d6b10 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v @@ -0,0 +1,428 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_macstatus.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_macstatus.v,v $ +// Revision 1.17 2005/03/21 20:07:18 igorm +// Some small fixes + some troubles fixed. +// +// Revision 1.16 2005/02/21 10:42:11 igorm +// Defer indication fixed. +// +// Revision 1.15 2003/01/30 13:28:19 tadejm +// Defer indication changed. +// +// Revision 1.14 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.13 2002/11/13 22:30:58 tadejm +// Late collision is reported only when not in the full duplex. +// Sample is taken (for status) as soon as MRxDV is not valid (regardless +// of the received byte cnt). +// +// Revision 1.12 2002/09/12 14:50:16 mohor +// CarrierSenseLost bug fixed when operating in full duplex mode. +// +// Revision 1.11 2002/09/04 18:38:03 mohor +// CarrierSenseLost status is not set when working in loopback mode. +// +// Revision 1.10 2002/07/25 18:17:46 mohor +// InvalidSymbol generation changed. +// +// Revision 1.9 2002/04/22 13:51:44 mohor +// Short frame and ReceivedLengthOK were not detected correctly. +// +// Revision 1.8 2002/02/18 10:40:17 mohor +// Small fixes. +// +// Revision 1.7 2002/02/15 17:07:39 mohor +// Status was not written correctly when frames were discarted because of +// address mismatch. +// +// Revision 1.6 2002/02/11 09:18:21 mohor +// Tx status is written back to the BD. +// +// Revision 1.5 2002/02/08 16:21:54 mohor +// Rx status is written back to the BD. +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// +// +// +// + +`include "timescale.v" + + +module eth_macstatus( + MRxClk, Reset, ReceivedLengthOK, ReceiveEnd, ReceivedPacketGood, RxCrcError, + MRxErr, MRxDV, RxStateSFD, RxStateData, RxStatePreamble, RxStateIdle, Transmitting, + RxByteCnt, RxByteCntEq0, RxByteCntGreat2, RxByteCntMaxFrame, + InvalidSymbol, MRxD, LatchedCrcError, Collision, CollValid, RxLateCollision, + r_RecSmall, r_MinFL, r_MaxFL, ShortFrame, DribbleNibble, ReceivedPacketTooBig, r_HugEn, + LoadRxStatus, StartTxDone, StartTxAbort, RetryCnt, RetryCntLatched, MTxClk, MaxCollisionOccured, + RetryLimit, LateCollision, LateCollLatched, DeferIndication, DeferLatched, RstDeferLatched, TxStartFrm, + StatePreamble, StateData, CarrierSense, CarrierSenseLost, TxUsedData, LatchedMRxErr, Loopback, + r_FullD + ); + + + +parameter Tp = 1; + + +input MRxClk; +input Reset; +input RxCrcError; +input MRxErr; +input MRxDV; + +input RxStateSFD; +input [1:0] RxStateData; +input RxStatePreamble; +input RxStateIdle; +input Transmitting; +input [15:0] RxByteCnt; +input RxByteCntEq0; +input RxByteCntGreat2; +input RxByteCntMaxFrame; +input [3:0] MRxD; +input Collision; +input [5:0] CollValid; +input r_RecSmall; +input [15:0] r_MinFL; +input [15:0] r_MaxFL; +input r_HugEn; +input StartTxDone; +input StartTxAbort; +input [3:0] RetryCnt; +input MTxClk; +input MaxCollisionOccured; +input LateCollision; +input DeferIndication; +input TxStartFrm; +input StatePreamble; +input [1:0] StateData; +input CarrierSense; +input TxUsedData; +input Loopback; +input r_FullD; + + +output ReceivedLengthOK; +output ReceiveEnd; +output ReceivedPacketGood; +output InvalidSymbol; +output LatchedCrcError; +output RxLateCollision; +output ShortFrame; +output DribbleNibble; +output ReceivedPacketTooBig; +output LoadRxStatus; +output [3:0] RetryCntLatched; +output RetryLimit; +output LateCollLatched; +output DeferLatched; +input RstDeferLatched; +output CarrierSenseLost; +output LatchedMRxErr; + + +reg ReceiveEnd; + +reg LatchedCrcError; +reg LatchedMRxErr; +reg LoadRxStatus; +reg InvalidSymbol; +reg [3:0] RetryCntLatched; +reg RetryLimit; +reg LateCollLatched; +reg DeferLatched; +reg CarrierSenseLost; + +wire TakeSample; +wire SetInvalidSymbol; // Invalid symbol was received during reception in 100Mbps + +// Crc error +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LatchedCrcError <=#Tp 1'b0; + else + if(RxStateSFD) + LatchedCrcError <=#Tp 1'b0; + else + if(RxStateData[0]) + LatchedCrcError <=#Tp RxCrcError & ~RxByteCntEq0; +end + + +// LatchedMRxErr +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LatchedMRxErr <=#Tp 1'b0; + else + if(MRxErr & MRxDV & (RxStatePreamble | RxStateSFD | (|RxStateData) | RxStateIdle & ~Transmitting)) + LatchedMRxErr <=#Tp 1'b1; + else + LatchedMRxErr <=#Tp 1'b0; +end + + +// ReceivedPacketGood +assign ReceivedPacketGood = ~LatchedCrcError; + + +// ReceivedLengthOK +assign ReceivedLengthOK = RxByteCnt[15:0] >= r_MinFL[15:0] & RxByteCnt[15:0] <= r_MaxFL[15:0]; + + + + + +// Time to take a sample +//assign TakeSample = |RxStateData & ~MRxDV & RxByteCntGreat2 | +assign TakeSample = (|RxStateData) & (~MRxDV) | + RxStateData[0] & MRxDV & RxByteCntMaxFrame; + + +// LoadRxStatus +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LoadRxStatus <=#Tp 1'b0; + else + LoadRxStatus <=#Tp TakeSample; +end + + + +// ReceiveEnd +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ReceiveEnd <=#Tp 1'b0; + else + ReceiveEnd <=#Tp LoadRxStatus; +end + + +// Invalid Symbol received during 100Mbps mode +assign SetInvalidSymbol = MRxDV & MRxErr & MRxD[3:0] == 4'he; + + +// InvalidSymbol +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + InvalidSymbol <=#Tp 1'b0; + else + if(LoadRxStatus & ~SetInvalidSymbol) + InvalidSymbol <=#Tp 1'b0; + else + if(SetInvalidSymbol) + InvalidSymbol <=#Tp 1'b1; +end + + +// Late Collision + +reg RxLateCollision; +reg RxColWindow; +// Collision Window +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxLateCollision <=#Tp 1'b0; + else + if(LoadRxStatus) + RxLateCollision <=#Tp 1'b0; + else + if(Collision & (~r_FullD) & (~RxColWindow | r_RecSmall)) + RxLateCollision <=#Tp 1'b1; +end + +// Collision Window +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxColWindow <=#Tp 1'b1; + else + if(~Collision & RxByteCnt[5:0] == CollValid[5:0] & RxStateData[1]) + RxColWindow <=#Tp 1'b0; + else + if(RxStateIdle) + RxColWindow <=#Tp 1'b1; +end + + +// ShortFrame +reg ShortFrame; +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ShortFrame <=#Tp 1'b0; + else + if(LoadRxStatus) + ShortFrame <=#Tp 1'b0; + else + if(TakeSample) + ShortFrame <=#Tp RxByteCnt[15:0] < r_MinFL[15:0]; +end + + +// DribbleNibble +reg DribbleNibble; +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + DribbleNibble <=#Tp 1'b0; + else + if(RxStateSFD) + DribbleNibble <=#Tp 1'b0; + else + if(~MRxDV & RxStateData[1]) + DribbleNibble <=#Tp 1'b1; +end + + +reg ReceivedPacketTooBig; +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ReceivedPacketTooBig <=#Tp 1'b0; + else + if(LoadRxStatus) + ReceivedPacketTooBig <=#Tp 1'b0; + else + if(TakeSample) + ReceivedPacketTooBig <=#Tp ~r_HugEn & RxByteCnt[15:0] > r_MaxFL[15:0]; +end + + + +// Latched Retry counter for tx status +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + RetryCntLatched <=#Tp 4'h0; + else + if(StartTxDone | StartTxAbort) + RetryCntLatched <=#Tp RetryCnt; +end + + +// Latched Retransmission limit +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + RetryLimit <=#Tp 1'h0; + else + if(StartTxDone | StartTxAbort) + RetryLimit <=#Tp MaxCollisionOccured; +end + + +// Latched Late Collision +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + LateCollLatched <=#Tp 1'b0; + else + if(StartTxDone | StartTxAbort) + LateCollLatched <=#Tp LateCollision; +end + + + +// Latched Defer state +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + DeferLatched <=#Tp 1'b0; + else + if(DeferIndication) + DeferLatched <=#Tp 1'b1; + else + if(RstDeferLatched) + DeferLatched <=#Tp 1'b0; +end + + +// CarrierSenseLost +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + CarrierSenseLost <=#Tp 1'b0; + else + if((StatePreamble | (|StateData)) & ~CarrierSense & ~Loopback & ~Collision & ~r_FullD) + CarrierSenseLost <=#Tp 1'b1; + else + if(TxStartFrm) + CarrierSenseLost <=#Tp 1'b0; +end + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v new file mode 100644 index 000000000..217012786 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v @@ -0,0 +1,451 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_miim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_miim.v,v $ +// Revision 1.7 2005/03/21 20:07:18 igorm +// Some small fixes + some troubles fixed. +// +// Revision 1.6 2005/02/21 12:48:07 igorm +// Warning fixes. +// +// Revision 1.5 2003/05/16 10:08:27 mohor +// Busy was set 2 cycles too late. Reported by Dennis Scott. +// +// Revision 1.4 2002/08/14 18:32:10 mohor +// - Busy signal was not set on time when scan status operation was performed +// and clock was divided with more than 2. +// - Nvalid remains valid two more clocks (was previously cleared too soon). +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.2 2001/08/02 09:25:31 mohor +// Unconnected signals are now connected. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`include "timescale.v" + + +module eth_miim +( + Clk, + Reset, + Divider, + NoPre, + CtrlData, + Rgad, + Fiad, + WCtrlData, + RStat, + ScanStat, + Mdi, + Mdo, + MdoEn, + Mdc, + Busy, + Prsd, + LinkFail, + Nvalid, + WCtrlDataStart, + RStatStart, + UpdateMIIRX_DATAReg +); + + + +input Clk; // Host Clock +input Reset; // General Reset +input [7:0] Divider; // Divider for the host clock +input [15:0] CtrlData; // Control Data (to be written to the PHY reg.) +input [4:0] Rgad; // Register Address (within the PHY) +input [4:0] Fiad; // PHY Address +input NoPre; // No Preamble (no 32-bit preamble) +input WCtrlData; // Write Control Data operation +input RStat; // Read Status operation +input ScanStat; // Scan Status operation +input Mdi; // MII Management Data In + +output Mdc; // MII Management Data Clock +output Mdo; // MII Management Data Output +output MdoEn; // MII Management Data Output Enable +output Busy; // Busy Signal +output LinkFail; // Link Integrity Signal +output Nvalid; // Invalid Status (qualifier for the valid scan result) + +output [15:0] Prsd; // Read Status Data (data read from the PHY) + +output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register +output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register +output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + +parameter Tp = 1; + + +reg Nvalid; +reg EndBusy_d; // Pre-end Busy signal +reg EndBusy; // End Busy signal (stops the operation in progress) + +reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle +reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles +reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles +reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected) +reg WCtrlDataStart_q; +reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle +reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles + +reg RStat_q1; // Read Status operation delayed 1 Clk cycle +reg RStat_q2; // Read Status operation delayed 2 Clk cycles +reg RStat_q3; // Read Status operation delayed 3 Clk cycles +reg RStatStart; // Start Read Status Command (positive edge detected) +reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle +reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles + +reg ScanStat_q1; // Scan Status operation delayed 1 cycle +reg ScanStat_q2; // Scan Status operation delayed 2 cycles +reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn + +wire WriteDataOp; // Write Data Operation (positive edge detected) +wire ReadStatusOp; // Read Status Operation (positive edge detected) +wire ScanStatusOp; // Scan Status Operation (positive edge detected) +wire StartOp; // Start Operation (start of any of the preceding operations) +wire EndOp; // End of Operation + +reg InProgress; // Operation in progress +reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle +reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles +reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles + +reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +reg [6:0] BitCounter; // Bit Counter + + +wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register. +wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises. +wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal +wire MdcEn_n; + +wire LatchByte1_d2; +wire LatchByte0_d2; +reg LatchByte1_d; +reg LatchByte0_d; +reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register + +reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + + + + + +// Generation of the EndBusy signal. It is used for ending the MII Management operation. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + EndBusy_d <= #Tp 1'b0; + EndBusy <= #Tp 1'b0; + end + else + begin + EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3; + EndBusy <= #Tp EndBusy_d; + end +end + + +// Update MII RX_DATA register +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + UpdateMIIRX_DATAReg <= #Tp 0; + else + if(EndBusy & ~WCtrlDataStart_q) + UpdateMIIRX_DATAReg <= #Tp 1; + else + UpdateMIIRX_DATAReg <= #Tp 0; +end + + + +// Generation of the delayed signals used for positive edge triggering. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlData_q1 <= #Tp 1'b0; + WCtrlData_q2 <= #Tp 1'b0; + WCtrlData_q3 <= #Tp 1'b0; + + RStat_q1 <= #Tp 1'b0; + RStat_q2 <= #Tp 1'b0; + RStat_q3 <= #Tp 1'b0; + + ScanStat_q1 <= #Tp 1'b0; + ScanStat_q2 <= #Tp 1'b0; + SyncStatMdcEn <= #Tp 1'b0; + end + else + begin + WCtrlData_q1 <= #Tp WCtrlData; + WCtrlData_q2 <= #Tp WCtrlData_q1; + WCtrlData_q3 <= #Tp WCtrlData_q2; + + RStat_q1 <= #Tp RStat; + RStat_q2 <= #Tp RStat_q1; + RStat_q3 <= #Tp RStat_q2; + + ScanStat_q1 <= #Tp ScanStat; + ScanStat_q2 <= #Tp ScanStat_q1; + if(MdcEn) + SyncStatMdcEn <= #Tp ScanStat_q2; + end +end + + +// Generation of the Start Commands (Write Control Data or Read Status) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart <= #Tp 1'b0; + WCtrlDataStart_q <= #Tp 1'b0; + RStatStart <= #Tp 1'b0; + end + else + begin + if(EndBusy) + begin + WCtrlDataStart <= #Tp 1'b0; + RStatStart <= #Tp 1'b0; + end + else + begin + if(WCtrlData_q2 & ~WCtrlData_q3) + WCtrlDataStart <= #Tp 1'b1; + if(RStat_q2 & ~RStat_q3) + RStatStart <= #Tp 1'b1; + WCtrlDataStart_q <= #Tp WCtrlDataStart; + end + end +end + + +// Generation of the Nvalid signal (indicates when the status is invalid) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Nvalid <= #Tp 1'b0; + else + begin + if(~InProgress_q2 & InProgress_q3) + begin + Nvalid <= #Tp 1'b0; + end + else + begin + if(ScanStat_q2 & ~SyncStatMdcEn) + Nvalid <= #Tp 1'b1; + end + end +end + +// Signals used for the generation of the Operation signals (positive edge) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart_q1 <= #Tp 1'b0; + WCtrlDataStart_q2 <= #Tp 1'b0; + + RStatStart_q1 <= #Tp 1'b0; + RStatStart_q2 <= #Tp 1'b0; + + InProgress_q1 <= #Tp 1'b0; + InProgress_q2 <= #Tp 1'b0; + InProgress_q3 <= #Tp 1'b0; + + LatchByte0_d <= #Tp 1'b0; + LatchByte1_d <= #Tp 1'b0; + + LatchByte <= #Tp 2'b00; + end + else + begin + if(MdcEn) + begin + WCtrlDataStart_q1 <= #Tp WCtrlDataStart; + WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1; + + RStatStart_q1 <= #Tp RStatStart; + RStatStart_q2 <= #Tp RStatStart_q1; + + LatchByte[0] <= #Tp LatchByte0_d; + LatchByte[1] <= #Tp LatchByte1_d; + + LatchByte0_d <= #Tp LatchByte0_d2; + LatchByte1_d <= #Tp LatchByte1_d2; + + InProgress_q1 <= #Tp InProgress; + InProgress_q2 <= #Tp InProgress_q1; + InProgress_q3 <= #Tp InProgress_q2; + end + end +end + + +// Generation of the Operation signals +assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2; +assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2; +assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2; +assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp; + +// Busy +assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid; + + +// Generation of the InProgress signal (indicates when an operation is in progress) +// Generation of the WriteOp signal (indicates when a write is in progress) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + InProgress <= #Tp 1'b0; + WriteOp <= #Tp 1'b0; + end + else + begin + if(MdcEn) + begin + if(StartOp) + begin + if(~InProgress) + WriteOp <= #Tp WriteDataOp; + InProgress <= #Tp 1'b1; + end + else + begin + if(EndOp) + begin + InProgress <= #Tp 1'b0; + WriteOp <= #Tp 1'b0; + end + end + end + end +end + + + +// Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + BitCounter[6:0] <= #Tp 7'h0; + else + begin + if(MdcEn) + begin + if(InProgress) + begin + if(NoPre & ( BitCounter == 7'h0 )) + BitCounter[6:0] <= #Tp 7'h21; + else + BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1; + end + else + BitCounter[6:0] <= #Tp 7'h0; + end + end +end + + +// Operation ends when the Bit Counter reaches 63 +assign EndOp = BitCounter==63; + +assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20))); +assign ByteSelect[1] = InProgress & (BitCounter == 7'h28); +assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30); +assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38); + + +// Latch Byte selects which part of Read Status Data is updated from the shift register +assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37; +assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F; + + +// Connecting the Clock Generator Module +eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc) + ); + +// Connecting the Shift Register Module +eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad), + .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte), + .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail) + ); + +// Connecting the Output Control Module +eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress), + .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre), + .Mdo(Mdo), .MdoEn(MdoEn) + ); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v new file mode 100644 index 000000000..bffdd6ac2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v @@ -0,0 +1,150 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_outputcontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_outputcontrol.v,v $ +// Revision 1.4 2002/07/09 20:11:59 mohor +// Comment removed. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`include "timescale.v" + +module eth_outputcontrol(Clk, Reset, InProgress, ShiftedBit, BitCounter, WriteOp, NoPre, MdcEn_n, Mdo, MdoEn); + +parameter Tp = 1; + +input Clk; // Host Clock +input Reset; // General Reset +input WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +input NoPre; // No Preamble (no 32-bit preamble) +input InProgress; // Operation in progress +input ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal +input [6:0] BitCounter; // Bit Counter +input MdcEn_n; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc falls. + +output Mdo; // MII Management Data Output +output MdoEn; // MII Management Data Output Enable + +wire SerialEn; + +reg MdoEn_2d; +reg MdoEn_d; +reg MdoEn; + +reg Mdo_2d; +reg Mdo_d; +reg Mdo; // MII Management Data Output + + + +// Generation of the Serial Enable signal (enables the serialization of the data) +assign SerialEn = WriteOp & InProgress & ( BitCounter>31 | ( ( BitCounter == 0 ) & NoPre ) ) + | ~WriteOp & InProgress & (( BitCounter>31 & BitCounter<46 ) | ( ( BitCounter == 0 ) & NoPre )); + + +// Generation of the MdoEn signal +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + MdoEn_2d <= #Tp 1'b0; + MdoEn_d <= #Tp 1'b0; + MdoEn <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + MdoEn_2d <= #Tp SerialEn | InProgress & BitCounter<32; + MdoEn_d <= #Tp MdoEn_2d; + MdoEn <= #Tp MdoEn_d; + end + end +end + + +// Generation of the Mdo signal. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + Mdo_2d <= #Tp 1'b0; + Mdo_d <= #Tp 1'b0; + Mdo <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + Mdo_2d <= #Tp ~SerialEn & BitCounter<32; + Mdo_d <= #Tp ShiftedBit | Mdo_2d; + Mdo <= #Tp Mdo_d; + end + end +end + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v new file mode 100644 index 000000000..9757e2498 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v @@ -0,0 +1,144 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_random.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_random.v,v $ +// Revision 1.4 2003/06/13 11:26:08 mohor +// Binary operator used instead of unary (xnor). +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/19 18:16:40 mohor +// TxClk changed to MTxClk (as discribed in the documentation). +// Crc changed so only one file can be used instead of two. +// +// Revision 1.2 2001/06/19 10:38:07 mohor +// Minor changes in header. +// +// Revision 1.1 2001/06/19 10:27:57 mohor +// TxEthMAC initial release. +// +// +// +// + +`include "timescale.v" + +module eth_random (MTxClk, Reset, StateJam, StateJam_q, RetryCnt, NibCnt, ByteCnt, + RandomEq0, RandomEqByteCnt); + +parameter Tp = 1; + +input MTxClk; +input Reset; +input StateJam; +input StateJam_q; +input [3:0] RetryCnt; +input [15:0] NibCnt; +input [9:0] ByteCnt; +output RandomEq0; +output RandomEqByteCnt; + +wire Feedback; +reg [9:0] x; +wire [9:0] Random; +reg [9:0] RandomLatched; + + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + x[9:0] <= #Tp 0; + else + x[9:0] <= #Tp {x[8:0], Feedback}; +end + +assign Feedback = ~(x[2] ^ x[9]); + +assign Random [0] = x[0]; +assign Random [1] = (RetryCnt > 1) ? x[1] : 1'b0; +assign Random [2] = (RetryCnt > 2) ? x[2] : 1'b0; +assign Random [3] = (RetryCnt > 3) ? x[3] : 1'b0; +assign Random [4] = (RetryCnt > 4) ? x[4] : 1'b0; +assign Random [5] = (RetryCnt > 5) ? x[5] : 1'b0; +assign Random [6] = (RetryCnt > 6) ? x[6] : 1'b0; +assign Random [7] = (RetryCnt > 7) ? x[7] : 1'b0; +assign Random [8] = (RetryCnt > 8) ? x[8] : 1'b0; +assign Random [9] = (RetryCnt > 9) ? x[9] : 1'b0; + + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + RandomLatched <= #Tp 10'h000; + else + begin + if(StateJam & StateJam_q) + RandomLatched <= #Tp Random; + end +end + +// Random Number == 0 IEEE 802.3 page 68. If 0 we go to defer and not to backoff. +assign RandomEq0 = RandomLatched == 10'h0; + +assign RandomEqByteCnt = ByteCnt[9:0] == RandomLatched & (&NibCnt[6:0]); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v new file mode 100644 index 000000000..2edec86b2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v @@ -0,0 +1,441 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_receivecontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_receivecontrol.v,v $ +// Revision 1.5 2003/01/22 13:49:26 tadejm +// When control packets were received, they were ignored in some cases. +// +// Revision 1.4 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.1 2001/07/03 12:51:54 mohor +// Initial release of the MAC Control module. +// +// +// +// +// + + +`include "timescale.v" + + +module eth_receivecontrol (MTxClk, MRxClk, TxReset, RxReset, RxData, RxValid, RxStartFrm, + RxEndFrm, RxFlow, ReceiveEnd, MAC, DlyCrcEn, TxDoneIn, + TxAbortIn, TxStartFrmOut, ReceivedLengthOK, ReceivedPacketGood, + TxUsedDataOutDetected, Pause, ReceivedPauseFrm, AddressOK, + RxStatusWriteLatched_sync2, r_PassAll, SetPauseTimer + ); + +parameter Tp = 1; + + +input MTxClk; +input MRxClk; +input TxReset; +input RxReset; +input [7:0] RxData; +input RxValid; +input RxStartFrm; +input RxEndFrm; +input RxFlow; +input ReceiveEnd; +input [47:0]MAC; +input DlyCrcEn; +input TxDoneIn; +input TxAbortIn; +input TxStartFrmOut; +input ReceivedLengthOK; +input ReceivedPacketGood; +input TxUsedDataOutDetected; +input RxStatusWriteLatched_sync2; +input r_PassAll; + +output Pause; +output ReceivedPauseFrm; +output AddressOK; +output SetPauseTimer; + + +reg Pause; +reg AddressOK; // Multicast or unicast address detected +reg TypeLengthOK; // Type/Length field contains 0x8808 +reg DetectionWindow; // Detection of the PAUSE frame is possible within this window +reg OpCodeOK; // PAUSE opcode detected (0x0001) +reg [2:0] DlyCrcCnt; +reg [4:0] ByteCnt; +reg [15:0] AssembledTimerValue; +reg [15:0] LatchedTimerValue; +reg ReceivedPauseFrm; +reg ReceivedPauseFrmWAddr; +reg PauseTimerEq0_sync1; +reg PauseTimerEq0_sync2; +reg [15:0] PauseTimer; +reg Divider2; +reg [5:0] SlotTimer; + +wire [47:0] ReservedMulticast; // 0x0180C2000001 +wire [15:0] TypeLength; // 0x8808 +wire ResetByteCnt; // +wire IncrementByteCnt; // +wire ByteCntEq0; // ByteCnt = 0 +wire ByteCntEq1; // ByteCnt = 1 +wire ByteCntEq2; // ByteCnt = 2 +wire ByteCntEq3; // ByteCnt = 3 +wire ByteCntEq4; // ByteCnt = 4 +wire ByteCntEq5; // ByteCnt = 5 +wire ByteCntEq12; // ByteCnt = 12 +wire ByteCntEq13; // ByteCnt = 13 +wire ByteCntEq14; // ByteCnt = 14 +wire ByteCntEq15; // ByteCnt = 15 +wire ByteCntEq16; // ByteCnt = 16 +wire ByteCntEq17; // ByteCnt = 17 +wire ByteCntEq18; // ByteCnt = 18 +wire DecrementPauseTimer; // +wire PauseTimerEq0; // +wire ResetSlotTimer; // +wire IncrementSlotTimer; // +wire SlotFinished; // + + + +// Reserved multicast address and Type/Length for PAUSE control +assign ReservedMulticast = 48'h0180C2000001; +assign TypeLength = 16'h8808; + + +// Address Detection (Multicast or unicast) +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + AddressOK <= #Tp 1'b0; + else + if(DetectionWindow & ByteCntEq0) + AddressOK <= #Tp RxData[7:0] == ReservedMulticast[47:40] | RxData[7:0] == MAC[47:40]; + else + if(DetectionWindow & ByteCntEq1) + AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[39:32] | RxData[7:0] == MAC[39:32]) & AddressOK; + else + if(DetectionWindow & ByteCntEq2) + AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[31:24] | RxData[7:0] == MAC[31:24]) & AddressOK; + else + if(DetectionWindow & ByteCntEq3) + AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[23:16] | RxData[7:0] == MAC[23:16]) & AddressOK; + else + if(DetectionWindow & ByteCntEq4) + AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[15:8] | RxData[7:0] == MAC[15:8]) & AddressOK; + else + if(DetectionWindow & ByteCntEq5) + AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[7:0] | RxData[7:0] == MAC[7:0]) & AddressOK; + else + if(ReceiveEnd) + AddressOK <= #Tp 1'b0; +end + + + +// TypeLengthOK (Type/Length Control frame detected) +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + TypeLengthOK <= #Tp 1'b0; + else + if(DetectionWindow & ByteCntEq12) + TypeLengthOK <= #Tp ByteCntEq12 & (RxData[7:0] == TypeLength[15:8]); + else + if(DetectionWindow & ByteCntEq13) + TypeLengthOK <= #Tp ByteCntEq13 & (RxData[7:0] == TypeLength[7:0]) & TypeLengthOK; + else + if(ReceiveEnd) + TypeLengthOK <= #Tp 1'b0; +end + + + +// Latch Control Frame Opcode +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + OpCodeOK <= #Tp 1'b0; + else + if(ByteCntEq16) + OpCodeOK <= #Tp 1'b0; + else + begin + if(DetectionWindow & ByteCntEq14) + OpCodeOK <= #Tp ByteCntEq14 & RxData[7:0] == 8'h00; + + if(DetectionWindow & ByteCntEq15) + OpCodeOK <= #Tp ByteCntEq15 & RxData[7:0] == 8'h01 & OpCodeOK; + end +end + + +// ReceivedPauseFrmWAddr (+Address Check) +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + ReceivedPauseFrmWAddr <= #Tp 1'b0; + else + if(ReceiveEnd) + ReceivedPauseFrmWAddr <= #Tp 1'b0; + else + if(ByteCntEq16 & TypeLengthOK & OpCodeOK & AddressOK) + ReceivedPauseFrmWAddr <= #Tp 1'b1; +end + + + +// Assembling 16-bit timer value from two 8-bit data +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + AssembledTimerValue[15:0] <= #Tp 16'h0; + else + if(RxStartFrm) + AssembledTimerValue[15:0] <= #Tp 16'h0; + else + begin + if(DetectionWindow & ByteCntEq16) + AssembledTimerValue[15:8] <= #Tp RxData[7:0]; + if(DetectionWindow & ByteCntEq17) + AssembledTimerValue[7:0] <= #Tp RxData[7:0]; + end +end + + +// Detection window (while PAUSE detection is possible) +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + DetectionWindow <= #Tp 1'b1; + else + if(ByteCntEq18) + DetectionWindow <= #Tp 1'b0; + else + if(ReceiveEnd) + DetectionWindow <= #Tp 1'b1; +end + + + +// Latching Timer Value +always @ (posedge MRxClk or posedge RxReset ) +begin + if(RxReset) + LatchedTimerValue[15:0] <= #Tp 16'h0; + else + if(DetectionWindow & ReceivedPauseFrmWAddr & ByteCntEq18) + LatchedTimerValue[15:0] <= #Tp AssembledTimerValue[15:0]; + else + if(ReceiveEnd) + LatchedTimerValue[15:0] <= #Tp 16'h0; +end + + + +// Delayed CEC counter +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + DlyCrcCnt <= #Tp 3'h0; + else + if(RxValid & RxEndFrm) + DlyCrcCnt <= #Tp 3'h0; + else + if(RxValid & ~RxEndFrm & ~DlyCrcCnt[2]) + DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1; +end + + +assign ResetByteCnt = RxEndFrm; +assign IncrementByteCnt = RxValid & DetectionWindow & ~ByteCntEq18 & (~DlyCrcEn | DlyCrcEn & DlyCrcCnt[2]); + + +// Byte counter +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + ByteCnt[4:0] <= #Tp 5'h0; + else + if(ResetByteCnt) + ByteCnt[4:0] <= #Tp 5'h0; + else + if(IncrementByteCnt) + ByteCnt[4:0] <= #Tp ByteCnt[4:0] + 1'b1; +end + + +assign ByteCntEq0 = RxValid & ByteCnt[4:0] == 5'h0; +assign ByteCntEq1 = RxValid & ByteCnt[4:0] == 5'h1; +assign ByteCntEq2 = RxValid & ByteCnt[4:0] == 5'h2; +assign ByteCntEq3 = RxValid & ByteCnt[4:0] == 5'h3; +assign ByteCntEq4 = RxValid & ByteCnt[4:0] == 5'h4; +assign ByteCntEq5 = RxValid & ByteCnt[4:0] == 5'h5; +assign ByteCntEq12 = RxValid & ByteCnt[4:0] == 5'h0C; +assign ByteCntEq13 = RxValid & ByteCnt[4:0] == 5'h0D; +assign ByteCntEq14 = RxValid & ByteCnt[4:0] == 5'h0E; +assign ByteCntEq15 = RxValid & ByteCnt[4:0] == 5'h0F; +assign ByteCntEq16 = RxValid & ByteCnt[4:0] == 5'h10; +assign ByteCntEq17 = RxValid & ByteCnt[4:0] == 5'h11; +assign ByteCntEq18 = RxValid & ByteCnt[4:0] == 5'h12 & DetectionWindow; + + +assign SetPauseTimer = ReceiveEnd & ReceivedPauseFrmWAddr & ReceivedPacketGood & ReceivedLengthOK & RxFlow; +assign DecrementPauseTimer = SlotFinished & |PauseTimer; + + +// PauseTimer[15:0] +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + PauseTimer[15:0] <= #Tp 16'h0; + else + if(SetPauseTimer) + PauseTimer[15:0] <= #Tp LatchedTimerValue[15:0]; + else + if(DecrementPauseTimer) + PauseTimer[15:0] <= #Tp PauseTimer[15:0] - 1'b1; +end + +assign PauseTimerEq0 = ~(|PauseTimer[15:0]); + + + +// Synchronization of the pause timer +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + begin + PauseTimerEq0_sync1 <= #Tp 1'b1; + PauseTimerEq0_sync2 <= #Tp 1'b1; + end + else + begin + PauseTimerEq0_sync1 <= #Tp PauseTimerEq0; + PauseTimerEq0_sync2 <= #Tp PauseTimerEq0_sync1; + end +end + + +// Pause signal generation +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + Pause <= #Tp 1'b0; + else + if((TxDoneIn | TxAbortIn | ~TxUsedDataOutDetected) & ~TxStartFrmOut) + Pause <= #Tp RxFlow & ~PauseTimerEq0_sync2; +end + + +// Divider2 is used for incrementing the Slot timer every other clock +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + Divider2 <= #Tp 1'b0; + else + if(|PauseTimer[15:0] & RxFlow) + Divider2 <= #Tp ~Divider2; + else + Divider2 <= #Tp 1'b0; +end + + +assign ResetSlotTimer = RxReset; +assign IncrementSlotTimer = Pause & RxFlow & Divider2; + + +// SlotTimer +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + SlotTimer[5:0] <= #Tp 6'h0; + else + if(ResetSlotTimer) + SlotTimer[5:0] <= #Tp 6'h0; + else + if(IncrementSlotTimer) + SlotTimer[5:0] <= #Tp SlotTimer[5:0] + 1'b1; +end + + +assign SlotFinished = &SlotTimer[5:0] & IncrementSlotTimer; // Slot is 512 bits (64 bytes) + + + +// Pause Frame received +always @ (posedge MRxClk or posedge RxReset) +begin + if(RxReset) + ReceivedPauseFrm <=#Tp 1'b0; + else + if(RxStatusWriteLatched_sync2 & r_PassAll | ReceivedPauseFrm & (~r_PassAll)) + ReceivedPauseFrm <=#Tp 1'b0; + else + if(ByteCntEq16 & TypeLengthOK & OpCodeOK) + ReceivedPauseFrm <=#Tp 1'b1; +end + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v new file mode 100644 index 000000000..265561e18 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v @@ -0,0 +1,111 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_register.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_register.v,v $ +// Revision 1.6 2002/08/16 22:10:12 mohor +// Synchronous reset added. +// +// Revision 1.5 2002/08/16 12:33:27 mohor +// Parameter ResetValue changed to capital letters. +// +// Revision 1.4 2002/02/26 16:18:08 mohor +// Reset values are passed to registers through parameters +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// +// +// +// +// +// + +`include "timescale.v" + + +module eth_register(DataIn, DataOut, Write, Clk, Reset, SyncReset); + +parameter WIDTH = 8; // default parameter of the register width +parameter RESET_VALUE = 0; + +input [WIDTH-1:0] DataIn; + +input Write; +input Clk; +input Reset; +input SyncReset; + +output [WIDTH-1:0] DataOut; +reg [WIDTH-1:0] DataOut; + + + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + DataOut<=#1 RESET_VALUE; + else + if(SyncReset) + DataOut<=#1 RESET_VALUE; + else + if(Write) // write + DataOut<=#1 DataIn; +end + + + +endmodule // Register diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v new file mode 100644 index 000000000..48aacc3d5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v @@ -0,0 +1,1184 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_registers.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_registers.v,v $ +// Revision 1.29 2005/03/21 20:07:18 igorm +// Some small fixes + some troubles fixed. +// +// Revision 1.28 2004/04/26 15:26:23 igorm +// - Bug connected to the TX_BD_NUM_Wr signal fixed (bug came in with the +// previous update of the core. +// - TxBDAddress is set to 0 after the TX is enabled in the MODER register. +// - RxBDAddress is set to r_TxBDNum<<1 after the RX is enabled in the MODER +// register. (thanks to Mathias and Torbjorn) +// - Multicast reception was fixed. Thanks to Ulrich Gries +// +// Revision 1.27 2004/04/26 11:42:17 igorm +// TX_BD_NUM_Wr error fixed. Error was entered with the last check-in. +// +// Revision 1.26 2003/11/12 18:24:59 tadejm +// WISHBONE slave changed and tested from only 32-bit accesss to byte access. +// +// Revision 1.25 2003/04/18 16:26:25 mohor +// RxBDAddress was updated also when value to r_TxBDNum was written with +// greater value than allowed. +// +// Revision 1.24 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.23 2002/11/19 18:13:49 mohor +// r_MiiMRst is not used for resetting the MIIM module. wb_rst used instead. +// +// Revision 1.22 2002/11/14 18:37:20 mohor +// r_Rst signal does not reset any module any more and is removed from the design. +// +// Revision 1.21 2002/09/10 10:35:23 mohor +// Ethernet debug registers removed. +// +// Revision 1.20 2002/09/04 18:40:25 mohor +// ETH_TXCTRL and ETH_RXCTRL registers added. Interrupts related to +// the control frames connected. +// +// Revision 1.19 2002/08/19 16:01:40 mohor +// Only values smaller or equal to 0x80 can be written to TX_BD_NUM register. +// r_TxEn and r_RxEn depend on the limit values of the TX_BD_NUMOut. +// +// Revision 1.18 2002/08/16 22:28:23 mohor +// Syntax error fixed. +// +// Revision 1.17 2002/08/16 22:23:03 mohor +// Syntax error fixed. +// +// Revision 1.16 2002/08/16 22:14:22 mohor +// Synchronous reset added to all registers. Defines used for width. r_MiiMRst +// changed from bit position 10 to 9. +// +// Revision 1.15 2002/08/14 18:26:37 mohor +// LinkFailRegister is reflecting the status of the PHY's link fail status bit. +// +// Revision 1.14 2002/04/22 14:03:44 mohor +// Interrupts are visible in the ETH_INT_SOURCE regardless if they are enabled +// or not. +// +// Revision 1.13 2002/02/26 16:18:09 mohor +// Reset values are passed to registers through parameters +// +// Revision 1.12 2002/02/17 13:23:42 mohor +// Define missmatch fixed. +// +// Revision 1.11 2002/02/16 14:03:44 mohor +// Registered trimmed. Unused registers removed. +// +// Revision 1.10 2002/02/15 11:08:25 mohor +// File format fixed a bit. +// +// Revision 1.9 2002/02/14 20:19:41 billditt +// Modified for Address Checking, +// addition of eth_addrcheck.v +// +// Revision 1.8 2002/02/12 17:01:19 mohor +// HASH0 and HASH1 registers added. + +// Revision 1.7 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.6 2001/12/05 15:00:16 mohor +// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors +// instead of the number of RX descriptors). +// +// Revision 1.5 2001/12/05 10:22:19 mohor +// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead. +// +// Revision 1.4 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.3 2001/10/18 12:07:11 mohor +// Status signals changed, Adress decoding changed, interrupt controller +// added. +// +// Revision 1.2 2001/09/24 15:02:56 mohor +// Defines changed (All precede with ETH_). Small changes because some +// tools generate warnings when two operands are together. Synchronization +// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC +// demands). +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.2 2001/08/02 09:25:31 mohor +// Unconnected signals are now connected. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// +// +// +// +// + +`include "eth_defines.v" +`include "timescale.v" + + +module eth_registers( DataIn, Address, Rw, Cs, Clk, Reset, DataOut, + r_RecSmall, r_Pad, r_HugEn, r_CrcEn, r_DlyCrcEn, + r_FullD, r_ExDfrEn, r_NoBckof, r_LoopBck, r_IFG, + r_Pro, r_Iam, r_Bro, r_NoPre, r_TxEn, r_RxEn, + TxB_IRQ, TxE_IRQ, RxB_IRQ, RxE_IRQ, Busy_IRQ, + r_IPGT, r_IPGR1, r_IPGR2, r_MinFL, r_MaxFL, r_MaxRet, + r_CollValid, r_TxFlow, r_RxFlow, r_PassAll, + r_MiiNoPre, r_ClkDiv, r_WCtrlData, r_RStat, r_ScanStat, + r_RGAD, r_FIAD, r_CtrlData, NValid_stat, Busy_stat, + LinkFail, r_MAC, WCtrlDataStart, RStatStart, + UpdateMIIRX_DATAReg, Prsd, r_TxBDNum, int_o, + r_HASH0, r_HASH1, r_TxPauseTV, r_TxPauseRq, RstTxPauseRq, TxCtrlEndFrm, + StartTxDone, TxClk, RxClk, SetPauseTimer + ); + +parameter Tp = 1; + +input [31:0] DataIn; +input [7:0] Address; + +input Rw; +input [3:0] Cs; +input Clk; +input Reset; + +input WCtrlDataStart; +input RStatStart; + +input UpdateMIIRX_DATAReg; +input [15:0] Prsd; + +output [31:0] DataOut; +reg [31:0] DataOut; + +output r_RecSmall; +output r_Pad; +output r_HugEn; +output r_CrcEn; +output r_DlyCrcEn; +output r_FullD; +output r_ExDfrEn; +output r_NoBckof; +output r_LoopBck; +output r_IFG; +output r_Pro; +output r_Iam; +output r_Bro; +output r_NoPre; +output r_TxEn; +output r_RxEn; +output [31:0] r_HASH0; +output [31:0] r_HASH1; + +input TxB_IRQ; +input TxE_IRQ; +input RxB_IRQ; +input RxE_IRQ; +input Busy_IRQ; + +output [6:0] r_IPGT; + +output [6:0] r_IPGR1; + +output [6:0] r_IPGR2; + +output [15:0] r_MinFL; +output [15:0] r_MaxFL; + +output [3:0] r_MaxRet; +output [5:0] r_CollValid; + +output r_TxFlow; +output r_RxFlow; +output r_PassAll; + +output r_MiiNoPre; +output [7:0] r_ClkDiv; + +output r_WCtrlData; +output r_RStat; +output r_ScanStat; + +output [4:0] r_RGAD; +output [4:0] r_FIAD; + +output [15:0]r_CtrlData; + + +input NValid_stat; +input Busy_stat; +input LinkFail; + +output [47:0]r_MAC; +output [7:0] r_TxBDNum; +output int_o; +output [15:0]r_TxPauseTV; +output r_TxPauseRq; +input RstTxPauseRq; +input TxCtrlEndFrm; +input StartTxDone; +input TxClk; +input RxClk; +input SetPauseTimer; + +reg irq_txb; +reg irq_txe; +reg irq_rxb; +reg irq_rxe; +reg irq_busy; +reg irq_txc; +reg irq_rxc; + +reg SetTxCIrq_txclk; +reg SetTxCIrq_sync1, SetTxCIrq_sync2, SetTxCIrq_sync3; +reg SetTxCIrq; +reg ResetTxCIrq_sync1, ResetTxCIrq_sync2; + +reg SetRxCIrq_rxclk; +reg SetRxCIrq_sync1, SetRxCIrq_sync2, SetRxCIrq_sync3; +reg SetRxCIrq; +reg ResetRxCIrq_sync1; +reg ResetRxCIrq_sync2; +reg ResetRxCIrq_sync3; + +wire [3:0] Write = Cs & {4{Rw}}; +wire Read = (|Cs) & ~Rw; + +wire MODER_Sel = (Address == `ETH_MODER_ADR ); +wire INT_SOURCE_Sel = (Address == `ETH_INT_SOURCE_ADR ); +wire INT_MASK_Sel = (Address == `ETH_INT_MASK_ADR ); +wire IPGT_Sel = (Address == `ETH_IPGT_ADR ); +wire IPGR1_Sel = (Address == `ETH_IPGR1_ADR ); +wire IPGR2_Sel = (Address == `ETH_IPGR2_ADR ); +wire PACKETLEN_Sel = (Address == `ETH_PACKETLEN_ADR ); +wire COLLCONF_Sel = (Address == `ETH_COLLCONF_ADR ); + +wire CTRLMODER_Sel = (Address == `ETH_CTRLMODER_ADR ); +wire MIIMODER_Sel = (Address == `ETH_MIIMODER_ADR ); +wire MIICOMMAND_Sel = (Address == `ETH_MIICOMMAND_ADR ); +wire MIIADDRESS_Sel = (Address == `ETH_MIIADDRESS_ADR ); +wire MIITX_DATA_Sel = (Address == `ETH_MIITX_DATA_ADR ); +wire MAC_ADDR0_Sel = (Address == `ETH_MAC_ADDR0_ADR ); +wire MAC_ADDR1_Sel = (Address == `ETH_MAC_ADDR1_ADR ); +wire HASH0_Sel = (Address == `ETH_HASH0_ADR ); +wire HASH1_Sel = (Address == `ETH_HASH1_ADR ); +wire TXCTRL_Sel = (Address == `ETH_TX_CTRL_ADR ); +wire RXCTRL_Sel = (Address == `ETH_RX_CTRL_ADR ); +wire TX_BD_NUM_Sel = (Address == `ETH_TX_BD_NUM_ADR ); + + +wire [2:0] MODER_Wr; +wire [0:0] INT_SOURCE_Wr; +wire [0:0] INT_MASK_Wr; +wire [0:0] IPGT_Wr; +wire [0:0] IPGR1_Wr; +wire [0:0] IPGR2_Wr; +wire [3:0] PACKETLEN_Wr; +wire [2:0] COLLCONF_Wr; +wire [0:0] CTRLMODER_Wr; +wire [1:0] MIIMODER_Wr; +wire [0:0] MIICOMMAND_Wr; +wire [1:0] MIIADDRESS_Wr; +wire [1:0] MIITX_DATA_Wr; +wire MIIRX_DATA_Wr; +wire [3:0] MAC_ADDR0_Wr; +wire [1:0] MAC_ADDR1_Wr; +wire [3:0] HASH0_Wr; +wire [3:0] HASH1_Wr; +wire [2:0] TXCTRL_Wr; +wire [0:0] TX_BD_NUM_Wr; + +assign MODER_Wr[0] = Write[0] & MODER_Sel; +assign MODER_Wr[1] = Write[1] & MODER_Sel; +assign MODER_Wr[2] = Write[2] & MODER_Sel; +assign INT_SOURCE_Wr[0] = Write[0] & INT_SOURCE_Sel; +assign INT_MASK_Wr[0] = Write[0] & INT_MASK_Sel; +assign IPGT_Wr[0] = Write[0] & IPGT_Sel; +assign IPGR1_Wr[0] = Write[0] & IPGR1_Sel; +assign IPGR2_Wr[0] = Write[0] & IPGR2_Sel; +assign PACKETLEN_Wr[0] = Write[0] & PACKETLEN_Sel; +assign PACKETLEN_Wr[1] = Write[1] & PACKETLEN_Sel; +assign PACKETLEN_Wr[2] = Write[2] & PACKETLEN_Sel; +assign PACKETLEN_Wr[3] = Write[3] & PACKETLEN_Sel; +assign COLLCONF_Wr[0] = Write[0] & COLLCONF_Sel; +assign COLLCONF_Wr[1] = 1'b0; // Not used +assign COLLCONF_Wr[2] = Write[2] & COLLCONF_Sel; + +assign CTRLMODER_Wr[0] = Write[0] & CTRLMODER_Sel; +assign MIIMODER_Wr[0] = Write[0] & MIIMODER_Sel; +assign MIIMODER_Wr[1] = Write[1] & MIIMODER_Sel; +assign MIICOMMAND_Wr[0] = Write[0] & MIICOMMAND_Sel; +assign MIIADDRESS_Wr[0] = Write[0] & MIIADDRESS_Sel; +assign MIIADDRESS_Wr[1] = Write[1] & MIIADDRESS_Sel; +assign MIITX_DATA_Wr[0] = Write[0] & MIITX_DATA_Sel; +assign MIITX_DATA_Wr[1] = Write[1] & MIITX_DATA_Sel; +assign MIIRX_DATA_Wr = UpdateMIIRX_DATAReg; +assign MAC_ADDR0_Wr[0] = Write[0] & MAC_ADDR0_Sel; +assign MAC_ADDR0_Wr[1] = Write[1] & MAC_ADDR0_Sel; +assign MAC_ADDR0_Wr[2] = Write[2] & MAC_ADDR0_Sel; +assign MAC_ADDR0_Wr[3] = Write[3] & MAC_ADDR0_Sel; +assign MAC_ADDR1_Wr[0] = Write[0] & MAC_ADDR1_Sel; +assign MAC_ADDR1_Wr[1] = Write[1] & MAC_ADDR1_Sel; +assign HASH0_Wr[0] = Write[0] & HASH0_Sel; +assign HASH0_Wr[1] = Write[1] & HASH0_Sel; +assign HASH0_Wr[2] = Write[2] & HASH0_Sel; +assign HASH0_Wr[3] = Write[3] & HASH0_Sel; +assign HASH1_Wr[0] = Write[0] & HASH1_Sel; +assign HASH1_Wr[1] = Write[1] & HASH1_Sel; +assign HASH1_Wr[2] = Write[2] & HASH1_Sel; +assign HASH1_Wr[3] = Write[3] & HASH1_Sel; +assign TXCTRL_Wr[0] = Write[0] & TXCTRL_Sel; +assign TXCTRL_Wr[1] = Write[1] & TXCTRL_Sel; +assign TXCTRL_Wr[2] = Write[2] & TXCTRL_Sel; +assign TX_BD_NUM_Wr[0] = Write[0] & TX_BD_NUM_Sel & (DataIn<='h80); + + + +wire [31:0] MODEROut; +wire [31:0] INT_SOURCEOut; +wire [31:0] INT_MASKOut; +wire [31:0] IPGTOut; +wire [31:0] IPGR1Out; +wire [31:0] IPGR2Out; +wire [31:0] PACKETLENOut; +wire [31:0] COLLCONFOut; +wire [31:0] CTRLMODEROut; +wire [31:0] MIIMODEROut; +wire [31:0] MIICOMMANDOut; +wire [31:0] MIIADDRESSOut; +wire [31:0] MIITX_DATAOut; +wire [31:0] MIIRX_DATAOut; +wire [31:0] MIISTATUSOut; +wire [31:0] MAC_ADDR0Out; +wire [31:0] MAC_ADDR1Out; +wire [31:0] TX_BD_NUMOut; +wire [31:0] HASH0Out; +wire [31:0] HASH1Out; +wire [31:0] TXCTRLOut; + +// MODER Register +eth_register #(`ETH_MODER_WIDTH_0, `ETH_MODER_DEF_0) MODER_0 + ( + .DataIn (DataIn[`ETH_MODER_WIDTH_0 - 1:0]), + .DataOut (MODEROut[`ETH_MODER_WIDTH_0 - 1:0]), + .Write (MODER_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MODER_WIDTH_1, `ETH_MODER_DEF_1) MODER_1 + ( + .DataIn (DataIn[`ETH_MODER_WIDTH_1 + 7:8]), + .DataOut (MODEROut[`ETH_MODER_WIDTH_1 + 7:8]), + .Write (MODER_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MODER_WIDTH_2, `ETH_MODER_DEF_2) MODER_2 + ( + .DataIn (DataIn[`ETH_MODER_WIDTH_2 + 15:16]), + .DataOut (MODEROut[`ETH_MODER_WIDTH_2 + 15:16]), + .Write (MODER_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MODEROut[31:`ETH_MODER_WIDTH_2 + 16] = 0; + +// INT_MASK Register +eth_register #(`ETH_INT_MASK_WIDTH_0, `ETH_INT_MASK_DEF_0) INT_MASK_0 + ( + .DataIn (DataIn[`ETH_INT_MASK_WIDTH_0 - 1:0]), + .DataOut (INT_MASKOut[`ETH_INT_MASK_WIDTH_0 - 1:0]), + .Write (INT_MASK_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign INT_MASKOut[31:`ETH_INT_MASK_WIDTH_0] = 0; + +// IPGT Register +eth_register #(`ETH_IPGT_WIDTH_0, `ETH_IPGT_DEF_0) IPGT_0 + ( + .DataIn (DataIn[`ETH_IPGT_WIDTH_0 - 1:0]), + .DataOut (IPGTOut[`ETH_IPGT_WIDTH_0 - 1:0]), + .Write (IPGT_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign IPGTOut[31:`ETH_IPGT_WIDTH_0] = 0; + +// IPGR1 Register +eth_register #(`ETH_IPGR1_WIDTH_0, `ETH_IPGR1_DEF_0) IPGR1_0 + ( + .DataIn (DataIn[`ETH_IPGR1_WIDTH_0 - 1:0]), + .DataOut (IPGR1Out[`ETH_IPGR1_WIDTH_0 - 1:0]), + .Write (IPGR1_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign IPGR1Out[31:`ETH_IPGR1_WIDTH_0] = 0; + +// IPGR2 Register +eth_register #(`ETH_IPGR2_WIDTH_0, `ETH_IPGR2_DEF_0) IPGR2_0 + ( + .DataIn (DataIn[`ETH_IPGR2_WIDTH_0 - 1:0]), + .DataOut (IPGR2Out[`ETH_IPGR2_WIDTH_0 - 1:0]), + .Write (IPGR2_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign IPGR2Out[31:`ETH_IPGR2_WIDTH_0] = 0; + +// PACKETLEN Register +eth_register #(`ETH_PACKETLEN_WIDTH_0, `ETH_PACKETLEN_DEF_0) PACKETLEN_0 + ( + .DataIn (DataIn[`ETH_PACKETLEN_WIDTH_0 - 1:0]), + .DataOut (PACKETLENOut[`ETH_PACKETLEN_WIDTH_0 - 1:0]), + .Write (PACKETLEN_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_PACKETLEN_WIDTH_1, `ETH_PACKETLEN_DEF_1) PACKETLEN_1 + ( + .DataIn (DataIn[`ETH_PACKETLEN_WIDTH_1 + 7:8]), + .DataOut (PACKETLENOut[`ETH_PACKETLEN_WIDTH_1 + 7:8]), + .Write (PACKETLEN_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_PACKETLEN_WIDTH_2, `ETH_PACKETLEN_DEF_2) PACKETLEN_2 + ( + .DataIn (DataIn[`ETH_PACKETLEN_WIDTH_2 + 15:16]), + .DataOut (PACKETLENOut[`ETH_PACKETLEN_WIDTH_2 + 15:16]), + .Write (PACKETLEN_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_PACKETLEN_WIDTH_3, `ETH_PACKETLEN_DEF_3) PACKETLEN_3 + ( + .DataIn (DataIn[`ETH_PACKETLEN_WIDTH_3 + 23:24]), + .DataOut (PACKETLENOut[`ETH_PACKETLEN_WIDTH_3 + 23:24]), + .Write (PACKETLEN_Wr[3]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); + +// COLLCONF Register +eth_register #(`ETH_COLLCONF_WIDTH_0, `ETH_COLLCONF_DEF_0) COLLCONF_0 + ( + .DataIn (DataIn[`ETH_COLLCONF_WIDTH_0 - 1:0]), + .DataOut (COLLCONFOut[`ETH_COLLCONF_WIDTH_0 - 1:0]), + .Write (COLLCONF_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_COLLCONF_WIDTH_2, `ETH_COLLCONF_DEF_2) COLLCONF_2 + ( + .DataIn (DataIn[`ETH_COLLCONF_WIDTH_2 + 15:16]), + .DataOut (COLLCONFOut[`ETH_COLLCONF_WIDTH_2 + 15:16]), + .Write (COLLCONF_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign COLLCONFOut[15:`ETH_COLLCONF_WIDTH_0] = 0; +assign COLLCONFOut[31:`ETH_COLLCONF_WIDTH_2 + 16] = 0; + +// TX_BD_NUM Register +eth_register #(`ETH_TX_BD_NUM_WIDTH_0, `ETH_TX_BD_NUM_DEF_0) TX_BD_NUM_0 + ( + .DataIn (DataIn[`ETH_TX_BD_NUM_WIDTH_0 - 1:0]), + .DataOut (TX_BD_NUMOut[`ETH_TX_BD_NUM_WIDTH_0 - 1:0]), + .Write (TX_BD_NUM_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign TX_BD_NUMOut[31:`ETH_TX_BD_NUM_WIDTH_0] = 0; + +// CTRLMODER Register +eth_register #(`ETH_CTRLMODER_WIDTH_0, `ETH_CTRLMODER_DEF_0) CTRLMODER_0 + ( + .DataIn (DataIn[`ETH_CTRLMODER_WIDTH_0 - 1:0]), + .DataOut (CTRLMODEROut[`ETH_CTRLMODER_WIDTH_0 - 1:0]), + .Write (CTRLMODER_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign CTRLMODEROut[31:`ETH_CTRLMODER_WIDTH_0] = 0; + +// MIIMODER Register +eth_register #(`ETH_MIIMODER_WIDTH_0, `ETH_MIIMODER_DEF_0) MIIMODER_0 + ( + .DataIn (DataIn[`ETH_MIIMODER_WIDTH_0 - 1:0]), + .DataOut (MIIMODEROut[`ETH_MIIMODER_WIDTH_0 - 1:0]), + .Write (MIIMODER_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MIIMODER_WIDTH_1, `ETH_MIIMODER_DEF_1) MIIMODER_1 + ( + .DataIn (DataIn[`ETH_MIIMODER_WIDTH_1 + 7:8]), + .DataOut (MIIMODEROut[`ETH_MIIMODER_WIDTH_1 + 7:8]), + .Write (MIIMODER_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MIIMODEROut[31:`ETH_MIIMODER_WIDTH_1 + 8] = 0; + +// MIICOMMAND Register +eth_register #(1, 0) MIICOMMAND0 + ( + .DataIn (DataIn[0]), + .DataOut (MIICOMMANDOut[0]), + .Write (MIICOMMAND_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(1, 0) MIICOMMAND1 + ( + .DataIn (DataIn[1]), + .DataOut (MIICOMMANDOut[1]), + .Write (MIICOMMAND_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (RStatStart) + ); +eth_register #(1, 0) MIICOMMAND2 + ( + .DataIn (DataIn[2]), + .DataOut (MIICOMMANDOut[2]), + .Write (MIICOMMAND_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (WCtrlDataStart) + ); +assign MIICOMMANDOut[31:`ETH_MIICOMMAND_WIDTH_0] = 29'h0; + +// MIIADDRESSRegister +eth_register #(`ETH_MIIADDRESS_WIDTH_0, `ETH_MIIADDRESS_DEF_0) MIIADDRESS_0 + ( + .DataIn (DataIn[`ETH_MIIADDRESS_WIDTH_0 - 1:0]), + .DataOut (MIIADDRESSOut[`ETH_MIIADDRESS_WIDTH_0 - 1:0]), + .Write (MIIADDRESS_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MIIADDRESS_WIDTH_1, `ETH_MIIADDRESS_DEF_1) MIIADDRESS_1 + ( + .DataIn (DataIn[`ETH_MIIADDRESS_WIDTH_1 + 7:8]), + .DataOut (MIIADDRESSOut[`ETH_MIIADDRESS_WIDTH_1 + 7:8]), + .Write (MIIADDRESS_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MIIADDRESSOut[7:`ETH_MIIADDRESS_WIDTH_0] = 0; +assign MIIADDRESSOut[31:`ETH_MIIADDRESS_WIDTH_1 + 8] = 0; + +// MIITX_DATA Register +eth_register #(`ETH_MIITX_DATA_WIDTH_0, `ETH_MIITX_DATA_DEF_0) MIITX_DATA_0 + ( + .DataIn (DataIn[`ETH_MIITX_DATA_WIDTH_0 - 1:0]), + .DataOut (MIITX_DATAOut[`ETH_MIITX_DATA_WIDTH_0 - 1:0]), + .Write (MIITX_DATA_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MIITX_DATA_WIDTH_1, `ETH_MIITX_DATA_DEF_1) MIITX_DATA_1 + ( + .DataIn (DataIn[`ETH_MIITX_DATA_WIDTH_1 + 7:8]), + .DataOut (MIITX_DATAOut[`ETH_MIITX_DATA_WIDTH_1 + 7:8]), + .Write (MIITX_DATA_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MIITX_DATAOut[31:`ETH_MIITX_DATA_WIDTH_1 + 8] = 0; + +// MIIRX_DATA Register +eth_register #(`ETH_MIIRX_DATA_WIDTH, `ETH_MIIRX_DATA_DEF) MIIRX_DATA + ( + .DataIn (Prsd[`ETH_MIIRX_DATA_WIDTH-1:0]), + .DataOut (MIIRX_DATAOut[`ETH_MIIRX_DATA_WIDTH-1:0]), + .Write (MIIRX_DATA_Wr), // not written from WB + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MIIRX_DATAOut[31:`ETH_MIIRX_DATA_WIDTH] = 0; + +// MAC_ADDR0 Register +eth_register #(`ETH_MAC_ADDR0_WIDTH_0, `ETH_MAC_ADDR0_DEF_0) MAC_ADDR0_0 + ( + .DataIn (DataIn[`ETH_MAC_ADDR0_WIDTH_0 - 1:0]), + .DataOut (MAC_ADDR0Out[`ETH_MAC_ADDR0_WIDTH_0 - 1:0]), + .Write (MAC_ADDR0_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MAC_ADDR0_WIDTH_1, `ETH_MAC_ADDR0_DEF_1) MAC_ADDR0_1 + ( + .DataIn (DataIn[`ETH_MAC_ADDR0_WIDTH_1 + 7:8]), + .DataOut (MAC_ADDR0Out[`ETH_MAC_ADDR0_WIDTH_1 + 7:8]), + .Write (MAC_ADDR0_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MAC_ADDR0_WIDTH_2, `ETH_MAC_ADDR0_DEF_2) MAC_ADDR0_2 + ( + .DataIn (DataIn[`ETH_MAC_ADDR0_WIDTH_2 + 15:16]), + .DataOut (MAC_ADDR0Out[`ETH_MAC_ADDR0_WIDTH_2 + 15:16]), + .Write (MAC_ADDR0_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MAC_ADDR0_WIDTH_3, `ETH_MAC_ADDR0_DEF_3) MAC_ADDR0_3 + ( + .DataIn (DataIn[`ETH_MAC_ADDR0_WIDTH_3 + 23:24]), + .DataOut (MAC_ADDR0Out[`ETH_MAC_ADDR0_WIDTH_3 + 23:24]), + .Write (MAC_ADDR0_Wr[3]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); + +// MAC_ADDR1 Register +eth_register #(`ETH_MAC_ADDR1_WIDTH_0, `ETH_MAC_ADDR1_DEF_0) MAC_ADDR1_0 + ( + .DataIn (DataIn[`ETH_MAC_ADDR1_WIDTH_0 - 1:0]), + .DataOut (MAC_ADDR1Out[`ETH_MAC_ADDR1_WIDTH_0 - 1:0]), + .Write (MAC_ADDR1_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_MAC_ADDR1_WIDTH_1, `ETH_MAC_ADDR1_DEF_1) MAC_ADDR1_1 + ( + .DataIn (DataIn[`ETH_MAC_ADDR1_WIDTH_1 + 7:8]), + .DataOut (MAC_ADDR1Out[`ETH_MAC_ADDR1_WIDTH_1 + 7:8]), + .Write (MAC_ADDR1_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +assign MAC_ADDR1Out[31:`ETH_MAC_ADDR1_WIDTH_1 + 8] = 0; + +// RXHASH0 Register +eth_register #(`ETH_HASH0_WIDTH_0, `ETH_HASH0_DEF_0) RXHASH0_0 + ( + .DataIn (DataIn[`ETH_HASH0_WIDTH_0 - 1:0]), + .DataOut (HASH0Out[`ETH_HASH0_WIDTH_0 - 1:0]), + .Write (HASH0_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH0_WIDTH_1, `ETH_HASH0_DEF_1) RXHASH0_1 + ( + .DataIn (DataIn[`ETH_HASH0_WIDTH_1 + 7:8]), + .DataOut (HASH0Out[`ETH_HASH0_WIDTH_1 + 7:8]), + .Write (HASH0_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH0_WIDTH_2, `ETH_HASH0_DEF_2) RXHASH0_2 + ( + .DataIn (DataIn[`ETH_HASH0_WIDTH_2 + 15:16]), + .DataOut (HASH0Out[`ETH_HASH0_WIDTH_2 + 15:16]), + .Write (HASH0_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH0_WIDTH_3, `ETH_HASH0_DEF_3) RXHASH0_3 + ( + .DataIn (DataIn[`ETH_HASH0_WIDTH_3 + 23:24]), + .DataOut (HASH0Out[`ETH_HASH0_WIDTH_3 + 23:24]), + .Write (HASH0_Wr[3]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); + +// RXHASH1 Register +eth_register #(`ETH_HASH1_WIDTH_0, `ETH_HASH1_DEF_0) RXHASH1_0 + ( + .DataIn (DataIn[`ETH_HASH1_WIDTH_0 - 1:0]), + .DataOut (HASH1Out[`ETH_HASH1_WIDTH_0 - 1:0]), + .Write (HASH1_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH1_WIDTH_1, `ETH_HASH1_DEF_1) RXHASH1_1 + ( + .DataIn (DataIn[`ETH_HASH1_WIDTH_1 + 7:8]), + .DataOut (HASH1Out[`ETH_HASH1_WIDTH_1 + 7:8]), + .Write (HASH1_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH1_WIDTH_2, `ETH_HASH1_DEF_2) RXHASH1_2 + ( + .DataIn (DataIn[`ETH_HASH1_WIDTH_2 + 15:16]), + .DataOut (HASH1Out[`ETH_HASH1_WIDTH_2 + 15:16]), + .Write (HASH1_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_HASH1_WIDTH_3, `ETH_HASH1_DEF_3) RXHASH1_3 + ( + .DataIn (DataIn[`ETH_HASH1_WIDTH_3 + 23:24]), + .DataOut (HASH1Out[`ETH_HASH1_WIDTH_3 + 23:24]), + .Write (HASH1_Wr[3]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); + +// TXCTRL Register +eth_register #(`ETH_TX_CTRL_WIDTH_0, `ETH_TX_CTRL_DEF_0) TXCTRL_0 + ( + .DataIn (DataIn[`ETH_TX_CTRL_WIDTH_0 - 1:0]), + .DataOut (TXCTRLOut[`ETH_TX_CTRL_WIDTH_0 - 1:0]), + .Write (TXCTRL_Wr[0]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_TX_CTRL_WIDTH_1, `ETH_TX_CTRL_DEF_1) TXCTRL_1 + ( + .DataIn (DataIn[`ETH_TX_CTRL_WIDTH_1 + 7:8]), + .DataOut (TXCTRLOut[`ETH_TX_CTRL_WIDTH_1 + 7:8]), + .Write (TXCTRL_Wr[1]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (1'b0) + ); +eth_register #(`ETH_TX_CTRL_WIDTH_2, `ETH_TX_CTRL_DEF_2) TXCTRL_2 // Request bit is synchronously reset + ( + .DataIn (DataIn[`ETH_TX_CTRL_WIDTH_2 + 15:16]), + .DataOut (TXCTRLOut[`ETH_TX_CTRL_WIDTH_2 + 15:16]), + .Write (TXCTRL_Wr[2]), + .Clk (Clk), + .Reset (Reset), + .SyncReset (RstTxPauseRq) + ); +assign TXCTRLOut[31:`ETH_TX_CTRL_WIDTH_2 + 16] = 0; + + + +// Reading data from registers +always @ (Address or Read or MODEROut or INT_SOURCEOut or + INT_MASKOut or IPGTOut or IPGR1Out or IPGR2Out or + PACKETLENOut or COLLCONFOut or CTRLMODEROut or MIIMODEROut or + MIICOMMANDOut or MIIADDRESSOut or MIITX_DATAOut or MIIRX_DATAOut or + MIISTATUSOut or MAC_ADDR0Out or MAC_ADDR1Out or TX_BD_NUMOut or + HASH0Out or HASH1Out or TXCTRLOut + ) +begin + if(Read) // read + begin + case(Address) + `ETH_MODER_ADR : DataOut<=MODEROut; + `ETH_INT_SOURCE_ADR : DataOut<=INT_SOURCEOut; + `ETH_INT_MASK_ADR : DataOut<=INT_MASKOut; + `ETH_IPGT_ADR : DataOut<=IPGTOut; + `ETH_IPGR1_ADR : DataOut<=IPGR1Out; + `ETH_IPGR2_ADR : DataOut<=IPGR2Out; + `ETH_PACKETLEN_ADR : DataOut<=PACKETLENOut; + `ETH_COLLCONF_ADR : DataOut<=COLLCONFOut; + `ETH_CTRLMODER_ADR : DataOut<=CTRLMODEROut; + `ETH_MIIMODER_ADR : DataOut<=MIIMODEROut; + `ETH_MIICOMMAND_ADR : DataOut<=MIICOMMANDOut; + `ETH_MIIADDRESS_ADR : DataOut<=MIIADDRESSOut; + `ETH_MIITX_DATA_ADR : DataOut<=MIITX_DATAOut; + `ETH_MIIRX_DATA_ADR : DataOut<=MIIRX_DATAOut; + `ETH_MIISTATUS_ADR : DataOut<=MIISTATUSOut; + `ETH_MAC_ADDR0_ADR : DataOut<=MAC_ADDR0Out; + `ETH_MAC_ADDR1_ADR : DataOut<=MAC_ADDR1Out; + `ETH_TX_BD_NUM_ADR : DataOut<=TX_BD_NUMOut; + `ETH_HASH0_ADR : DataOut<=HASH0Out; + `ETH_HASH1_ADR : DataOut<=HASH1Out; + `ETH_TX_CTRL_ADR : DataOut<=TXCTRLOut; + + default: DataOut<=32'h0; + endcase + end + else + DataOut<=32'h0; +end + + +assign r_RecSmall = MODEROut[16]; +assign r_Pad = MODEROut[15]; +assign r_HugEn = MODEROut[14]; +assign r_CrcEn = MODEROut[13]; +assign r_DlyCrcEn = MODEROut[12]; +// assign r_Rst = MODEROut[11]; This signal is not used any more +assign r_FullD = MODEROut[10]; +assign r_ExDfrEn = MODEROut[9]; +assign r_NoBckof = MODEROut[8]; +assign r_LoopBck = MODEROut[7]; +assign r_IFG = MODEROut[6]; +assign r_Pro = MODEROut[5]; +assign r_Iam = MODEROut[4]; +assign r_Bro = MODEROut[3]; +assign r_NoPre = MODEROut[2]; +assign r_TxEn = MODEROut[1] & (TX_BD_NUMOut>0); // Transmission is enabled when there is at least one TxBD. +assign r_RxEn = MODEROut[0] & (TX_BD_NUMOut<'h80); // Reception is enabled when there is at least one RxBD. + +assign r_IPGT[6:0] = IPGTOut[6:0]; + +assign r_IPGR1[6:0] = IPGR1Out[6:0]; + +assign r_IPGR2[6:0] = IPGR2Out[6:0]; + +assign r_MinFL[15:0] = PACKETLENOut[31:16]; +assign r_MaxFL[15:0] = PACKETLENOut[15:0]; + +assign r_MaxRet[3:0] = COLLCONFOut[19:16]; +assign r_CollValid[5:0] = COLLCONFOut[5:0]; + +assign r_TxFlow = CTRLMODEROut[2]; +assign r_RxFlow = CTRLMODEROut[1]; +assign r_PassAll = CTRLMODEROut[0]; + +assign r_MiiNoPre = MIIMODEROut[8]; +assign r_ClkDiv[7:0] = MIIMODEROut[7:0]; + +assign r_WCtrlData = MIICOMMANDOut[2]; +assign r_RStat = MIICOMMANDOut[1]; +assign r_ScanStat = MIICOMMANDOut[0]; + +assign r_RGAD[4:0] = MIIADDRESSOut[12:8]; +assign r_FIAD[4:0] = MIIADDRESSOut[4:0]; + +assign r_CtrlData[15:0] = MIITX_DATAOut[15:0]; + +assign MIISTATUSOut[31:`ETH_MIISTATUS_WIDTH] = 0; +assign MIISTATUSOut[2] = NValid_stat ; +assign MIISTATUSOut[1] = Busy_stat ; +assign MIISTATUSOut[0] = LinkFail ; + +assign r_MAC[31:0] = MAC_ADDR0Out[31:0]; +assign r_MAC[47:32] = MAC_ADDR1Out[15:0]; +assign r_HASH1[31:0] = HASH1Out; +assign r_HASH0[31:0] = HASH0Out; + +assign r_TxBDNum[7:0] = TX_BD_NUMOut[7:0]; + +assign r_TxPauseTV[15:0] = TXCTRLOut[15:0]; +assign r_TxPauseRq = TXCTRLOut[16]; + + +// Synchronizing TxC Interrupt +always @ (posedge TxClk or posedge Reset) +begin + if(Reset) + SetTxCIrq_txclk <=#Tp 1'b0; + else + if(TxCtrlEndFrm & StartTxDone & r_TxFlow) + SetTxCIrq_txclk <=#Tp 1'b1; + else + if(ResetTxCIrq_sync2) + SetTxCIrq_txclk <=#Tp 1'b0; +end + + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetTxCIrq_sync1 <=#Tp 1'b0; + else + SetTxCIrq_sync1 <=#Tp SetTxCIrq_txclk; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetTxCIrq_sync2 <=#Tp 1'b0; + else + SetTxCIrq_sync2 <=#Tp SetTxCIrq_sync1; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetTxCIrq_sync3 <=#Tp 1'b0; + else + SetTxCIrq_sync3 <=#Tp SetTxCIrq_sync2; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetTxCIrq <=#Tp 1'b0; + else + SetTxCIrq <=#Tp SetTxCIrq_sync2 & ~SetTxCIrq_sync3; +end + +always @ (posedge TxClk or posedge Reset) +begin + if(Reset) + ResetTxCIrq_sync1 <=#Tp 1'b0; + else + ResetTxCIrq_sync1 <=#Tp SetTxCIrq_sync2; +end + +always @ (posedge TxClk or posedge Reset) +begin + if(Reset) + ResetTxCIrq_sync2 <=#Tp 1'b0; + else + ResetTxCIrq_sync2 <=#Tp SetTxCIrq_sync1; +end + + +// Synchronizing RxC Interrupt +always @ (posedge RxClk or posedge Reset) +begin + if(Reset) + SetRxCIrq_rxclk <=#Tp 1'b0; + else + if(SetPauseTimer & r_RxFlow) + SetRxCIrq_rxclk <=#Tp 1'b1; + else + if(ResetRxCIrq_sync2 & (~ResetRxCIrq_sync3)) + SetRxCIrq_rxclk <=#Tp 1'b0; +end + + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetRxCIrq_sync1 <=#Tp 1'b0; + else + SetRxCIrq_sync1 <=#Tp SetRxCIrq_rxclk; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetRxCIrq_sync2 <=#Tp 1'b0; + else + SetRxCIrq_sync2 <=#Tp SetRxCIrq_sync1; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetRxCIrq_sync3 <=#Tp 1'b0; + else + SetRxCIrq_sync3 <=#Tp SetRxCIrq_sync2; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + SetRxCIrq <=#Tp 1'b0; + else + SetRxCIrq <=#Tp SetRxCIrq_sync2 & ~SetRxCIrq_sync3; +end + +always @ (posedge RxClk or posedge Reset) +begin + if(Reset) + ResetRxCIrq_sync1 <=#Tp 1'b0; + else + ResetRxCIrq_sync1 <=#Tp SetRxCIrq_sync2; +end + +always @ (posedge RxClk or posedge Reset) +begin + if(Reset) + ResetRxCIrq_sync2 <=#Tp 1'b0; + else + ResetRxCIrq_sync2 <=#Tp ResetRxCIrq_sync1; +end + +always @ (posedge RxClk or posedge Reset) +begin + if(Reset) + ResetRxCIrq_sync3 <=#Tp 1'b0; + else + ResetRxCIrq_sync3 <=#Tp ResetRxCIrq_sync2; +end + + + +// Interrupt generation +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_txb <= 1'b0; + else + if(TxB_IRQ) + irq_txb <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[0]) + irq_txb <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_txe <= 1'b0; + else + if(TxE_IRQ) + irq_txe <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[1]) + irq_txe <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_rxb <= 1'b0; + else + if(RxB_IRQ) + irq_rxb <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[2]) + irq_rxb <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_rxe <= 1'b0; + else + if(RxE_IRQ) + irq_rxe <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[3]) + irq_rxe <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_busy <= 1'b0; + else + if(Busy_IRQ) + irq_busy <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[4]) + irq_busy <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_txc <= 1'b0; + else + if(SetTxCIrq) + irq_txc <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[5]) + irq_txc <= #Tp 1'b0; +end + +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + irq_rxc <= 1'b0; + else + if(SetRxCIrq) + irq_rxc <= #Tp 1'b1; + else + if(INT_SOURCE_Wr[0] & DataIn[6]) + irq_rxc <= #Tp 1'b0; +end + +// Generating interrupt signal +assign int_o = irq_txb & INT_MASKOut[0] | + irq_txe & INT_MASKOut[1] | + irq_rxb & INT_MASKOut[2] | + irq_rxe & INT_MASKOut[3] | + irq_busy & INT_MASKOut[4] | + irq_txc & INT_MASKOut[5] | + irq_rxc & INT_MASKOut[6] ; + +// For reading interrupt status +assign INT_SOURCEOut = {{(32-`ETH_INT_SOURCE_WIDTH_0){1'b0}}, irq_rxc, irq_txc, irq_busy, irq_rxe, irq_rxb, irq_txe, irq_txb}; + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v new file mode 100644 index 000000000..b357cf617 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v @@ -0,0 +1,211 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_rxaddrcheck.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/cores/ethmac/ //// +//// //// +//// Author(s): //// +//// - Bill Dittenhofer (billditt@aol.com) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_rxaddrcheck.v,v $ +// Revision 1.9 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.8 2002/11/19 17:34:52 mohor +// AddressMiss status is connecting to the Rx BD. AddressMiss is identifying +// that a frame was received because of the promiscous mode. +// +// Revision 1.7 2002/09/04 18:41:06 mohor +// Bug when last byte of destination address was not checked fixed. +// +// Revision 1.6 2002/03/20 15:14:11 mohor +// When in promiscous mode some frames were not received correctly. Fixed. +// +// Revision 1.5 2002/03/02 21:06:32 mohor +// Log info was missing. +// +// +// Revision 1.1 2002/02/08 12:51:54 ditt +// Initial release of the ethernet addresscheck module. +// +// +// +// +// + + +`include "timescale.v" + + +module eth_rxaddrcheck(MRxClk, Reset, RxData, Broadcast ,r_Bro ,r_Pro, + ByteCntEq2, ByteCntEq3, ByteCntEq4, ByteCntEq5, + ByteCntEq6, ByteCntEq7, HASH0, HASH1, + CrcHash, CrcHashGood, StateData, RxEndFrm, + Multicast, MAC, RxAbort, AddressMiss, PassAll, + ControlFrmAddressOK + ); + +parameter Tp = 1; + + input MRxClk; + input Reset; + input [7:0] RxData; + input Broadcast; + input r_Bro; + input r_Pro; + input ByteCntEq2; + input ByteCntEq3; + input ByteCntEq4; + input ByteCntEq5; + input ByteCntEq6; + input ByteCntEq7; + input [31:0] HASH0; + input [31:0] HASH1; + input [5:0] CrcHash; + input CrcHashGood; + input Multicast; + input [47:0] MAC; + input [1:0] StateData; + input RxEndFrm; + input PassAll; + input ControlFrmAddressOK; + + output RxAbort; + output AddressMiss; + + wire BroadcastOK; + wire ByteCntEq2; + wire ByteCntEq3; + wire ByteCntEq4; + wire ByteCntEq5; + wire RxAddressInvalid; + wire RxCheckEn; + wire HashBit; + wire [31:0] IntHash; + reg [7:0] ByteHash; + reg MulticastOK; + reg UnicastOK; + reg RxAbort; + reg AddressMiss; + +assign RxAddressInvalid = ~(UnicastOK | BroadcastOK | MulticastOK | r_Pro); + +assign BroadcastOK = Broadcast & ~r_Bro; + +assign RxCheckEn = | StateData; + + // Address Error Reported at end of address cycle + // RxAbort clears after one cycle + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxAbort <= #Tp 1'b0; + else if(RxAddressInvalid & ByteCntEq7 & RxCheckEn) + RxAbort <= #Tp 1'b1; + else + RxAbort <= #Tp 1'b0; +end + + +// This ff holds the "Address Miss" information that is written to the RX BD status. +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + AddressMiss <= #Tp 1'b0; + else if(ByteCntEq7 & RxCheckEn) + AddressMiss <= #Tp (~(UnicastOK | BroadcastOK | MulticastOK | (PassAll & ControlFrmAddressOK))); +end + + +// Hash Address Check, Multicast +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + MulticastOK <= #Tp 1'b0; + else if(RxEndFrm | RxAbort) + MulticastOK <= #Tp 1'b0; + else if(CrcHashGood & Multicast) + MulticastOK <= #Tp HashBit; +end + + +// Address Detection (unicast) +// start with ByteCntEq2 due to delay of addres from RxData +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + UnicastOK <= #Tp 1'b0; + else + if(RxCheckEn & ByteCntEq2) + UnicastOK <= #Tp RxData[7:0] == MAC[47:40]; + else + if(RxCheckEn & ByteCntEq3) + UnicastOK <= #Tp ( RxData[7:0] == MAC[39:32]) & UnicastOK; + else + if(RxCheckEn & ByteCntEq4) + UnicastOK <= #Tp ( RxData[7:0] == MAC[31:24]) & UnicastOK; + else + if(RxCheckEn & ByteCntEq5) + UnicastOK <= #Tp ( RxData[7:0] == MAC[23:16]) & UnicastOK; + else + if(RxCheckEn & ByteCntEq6) + UnicastOK <= #Tp ( RxData[7:0] == MAC[15:8]) & UnicastOK; + else + if(RxCheckEn & ByteCntEq7) + UnicastOK <= #Tp ( RxData[7:0] == MAC[7:0]) & UnicastOK; + else + if(RxEndFrm | RxAbort) + UnicastOK <= #Tp 1'b0; +end + +assign IntHash = (CrcHash[5])? HASH1 : HASH0; + +always@(CrcHash or IntHash) +begin + case(CrcHash[4:3]) + 2'b00: ByteHash = IntHash[7:0]; + 2'b01: ByteHash = IntHash[15:8]; + 2'b10: ByteHash = IntHash[23:16]; + 2'b11: ByteHash = IntHash[31:24]; + endcase +end + +assign HashBit = ByteHash[CrcHash[2:0]]; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v new file mode 100644 index 000000000..7ff678e30 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v @@ -0,0 +1,221 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_rxcounters.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_rxcounters.v,v $ +// Revision 1.6 2005/02/21 11:00:57 igorm +// Delayed CRC fixed. +// +// Revision 1.5 2002/02/15 11:13:29 mohor +// Format of the file changed a bit. +// +// Revision 1.4 2002/02/14 20:19:41 billditt +// Modified for Address Checking, +// addition of eth_addrcheck.v +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.1 2001/06/27 21:26:19 mohor +// Initial release of the RxEthMAC module. +// +// +// +// +// +// + + +`include "timescale.v" + + +module eth_rxcounters (MRxClk, Reset, MRxDV, StateIdle, StateSFD, StateData, StateDrop, StatePreamble, + MRxDEqD, DlyCrcEn, DlyCrcCnt, Transmitting, MaxFL, r_IFG, HugEn, IFGCounterEq24, + ByteCntEq0, ByteCntEq1, ByteCntEq2,ByteCntEq3,ByteCntEq4,ByteCntEq5, ByteCntEq6, + ByteCntEq7, ByteCntGreat2, ByteCntSmall7, ByteCntMaxFrame, ByteCntOut + ); + +parameter Tp = 1; + +input MRxClk; +input Reset; +input MRxDV; +input StateSFD; +input [1:0] StateData; +input MRxDEqD; +input StateIdle; +input StateDrop; +input DlyCrcEn; +input StatePreamble; +input Transmitting; +input HugEn; +input [15:0] MaxFL; +input r_IFG; + +output IFGCounterEq24; // IFG counter reaches 9600 ns (960 ns) +output [3:0] DlyCrcCnt; // Delayed CRC counter +output ByteCntEq0; // Byte counter = 0 +output ByteCntEq1; // Byte counter = 1 +output ByteCntEq2; // Byte counter = 2 +output ByteCntEq3; // Byte counter = 3 +output ByteCntEq4; // Byte counter = 4 +output ByteCntEq5; // Byte counter = 5 +output ByteCntEq6; // Byte counter = 6 +output ByteCntEq7; // Byte counter = 7 +output ByteCntGreat2; // Byte counter > 2 +output ByteCntSmall7; // Byte counter < 7 +output ByteCntMaxFrame; // Byte counter = MaxFL +output [15:0] ByteCntOut; // Byte counter + +wire ResetByteCounter; +wire IncrementByteCounter; +wire ResetIFGCounter; +wire IncrementIFGCounter; +wire ByteCntMax; + +reg [15:0] ByteCnt; +reg [3:0] DlyCrcCnt; +reg [4:0] IFGCounter; + +wire [15:0] ByteCntDelayed; + + + +assign ResetByteCounter = MRxDV & (StateSFD & MRxDEqD | StateData[0] & ByteCntMaxFrame); + +assign IncrementByteCounter = ~ResetByteCounter & MRxDV & + (StatePreamble | StateSFD | StateIdle & ~Transmitting | + StateData[1] & ~ByteCntMax & ~(DlyCrcEn & |DlyCrcCnt) + ); + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ByteCnt[15:0] <= #Tp 16'h0; + else + begin + if(ResetByteCounter) + ByteCnt[15:0] <= #Tp 16'h0; + else + if(IncrementByteCounter) + ByteCnt[15:0] <= #Tp ByteCnt[15:0] + 1'b1; + end +end + +assign ByteCntDelayed = ByteCnt + 3'h4; +assign ByteCntOut = DlyCrcEn? ByteCntDelayed : ByteCnt; + +assign ByteCntEq0 = ByteCnt == 16'h0; +assign ByteCntEq1 = ByteCnt == 16'h1; +assign ByteCntEq2 = ByteCnt == 16'h2; +assign ByteCntEq3 = ByteCnt == 16'h3; +assign ByteCntEq4 = ByteCnt == 16'h4; +assign ByteCntEq5 = ByteCnt == 16'h5; +assign ByteCntEq6 = ByteCnt == 16'h6; +assign ByteCntEq7 = ByteCnt == 16'h7; +assign ByteCntGreat2 = ByteCnt > 16'h2; +assign ByteCntSmall7 = ByteCnt < 16'h7; +assign ByteCntMax = ByteCnt == 16'hffff; +assign ByteCntMaxFrame = ByteCnt == MaxFL[15:0] & ~HugEn; + + +assign ResetIFGCounter = StateSFD & MRxDV & MRxDEqD | StateDrop; + +assign IncrementIFGCounter = ~ResetIFGCounter & (StateDrop | StateIdle | StatePreamble | StateSFD) & ~IFGCounterEq24; + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + IFGCounter[4:0] <= #Tp 5'h0; + else + begin + if(ResetIFGCounter) + IFGCounter[4:0] <= #Tp 5'h0; + else + if(IncrementIFGCounter) + IFGCounter[4:0] <= #Tp IFGCounter[4:0] + 1'b1; + end +end + + + +assign IFGCounterEq24 = (IFGCounter[4:0] == 5'h18) | r_IFG; // 24*400 = 9600 ns or r_IFG is set to 1 + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + DlyCrcCnt[3:0] <= #Tp 4'h0; + else + begin + if(DlyCrcCnt[3:0] == 4'h9) + DlyCrcCnt[3:0] <= #Tp 4'h0; + else + if(DlyCrcEn & StateSFD) + DlyCrcCnt[3:0] <= #Tp 4'h1; + else + if(DlyCrcEn & (|DlyCrcCnt[3:0])) + DlyCrcCnt[3:0] <= #Tp DlyCrcCnt[3:0] + 1'b1; + end +end + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v new file mode 100644 index 000000000..c68c805e1 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v @@ -0,0 +1,380 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_rxethmac.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_rxethmac.v,v $ +// Revision 1.13 2005/02/21 12:48:07 igorm +// Warning fixes. +// +// Revision 1.12 2004/04/26 15:26:23 igorm +// - Bug connected to the TX_BD_NUM_Wr signal fixed (bug came in with the +// previous update of the core. +// - TxBDAddress is set to 0 after the TX is enabled in the MODER register. +// - RxBDAddress is set to r_TxBDNum<<1 after the RX is enabled in the MODER +// register. (thanks to Mathias and Torbjorn) +// - Multicast reception was fixed. Thanks to Ulrich Gries +// +// Revision 1.11 2004/03/17 09:32:15 igorm +// Multicast detection fixed. Only the LSB of the first byte is checked. +// +// Revision 1.10 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.9 2002/11/19 17:35:35 mohor +// AddressMiss status is connecting to the Rx BD. AddressMiss is identifying +// that a frame was received because of the promiscous mode. +// +// Revision 1.8 2002/02/16 07:15:27 mohor +// Testbench fixed, code simplified, unused signals removed. +// +// Revision 1.7 2002/02/15 13:44:28 mohor +// RxAbort is an output. No need to have is declared as wire. +// +// Revision 1.6 2002/02/15 11:17:48 mohor +// File format changed. +// +// Revision 1.5 2002/02/14 20:48:43 billditt +// Addition of new module eth_addrcheck.v +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.1 2001/06/27 21:26:19 mohor +// Initial release of the RxEthMAC module. +// +// +// +// +// + +`include "timescale.v" + + +module eth_rxethmac (MRxClk, MRxDV, MRxD, Reset, Transmitting, MaxFL, r_IFG, HugEn, DlyCrcEn, + RxData, RxValid, RxStartFrm, RxEndFrm, ByteCnt, ByteCntEq0, ByteCntGreat2, + ByteCntMaxFrame, CrcError, StateIdle, StatePreamble, StateSFD, StateData, + MAC, r_Pro, r_Bro,r_HASH0, r_HASH1, RxAbort, AddressMiss, PassAll, ControlFrmAddressOK + ); + +parameter Tp = 1; + + + +input MRxClk; +input MRxDV; +input [3:0] MRxD; +input Transmitting; +input HugEn; +input DlyCrcEn; +input [15:0] MaxFL; +input r_IFG; +input Reset; +input [47:0] MAC; // Station Address +input r_Bro; // broadcast disable +input r_Pro; // promiscuous enable +input [31:0] r_HASH0; // lower 4 bytes Hash Table +input [31:0] r_HASH1; // upper 4 bytes Hash Table +input PassAll; +input ControlFrmAddressOK; + +output [7:0] RxData; +output RxValid; +output RxStartFrm; +output RxEndFrm; +output [15:0] ByteCnt; +output ByteCntEq0; +output ByteCntGreat2; +output ByteCntMaxFrame; +output CrcError; +output StateIdle; +output StatePreamble; +output StateSFD; +output [1:0] StateData; +output RxAbort; +output AddressMiss; + +reg [7:0] RxData; +reg RxValid; +reg RxStartFrm; +reg RxEndFrm; +reg Broadcast; +reg Multicast; +reg [5:0] CrcHash; +reg CrcHashGood; +reg DelayData; +reg [7:0] LatchedByte; +reg [7:0] RxData_d; +reg RxValid_d; +reg RxStartFrm_d; +reg RxEndFrm_d; + +wire MRxDEqD; +wire MRxDEq5; +wire StateDrop; +wire ByteCntEq1; +wire ByteCntEq2; +wire ByteCntEq3; +wire ByteCntEq4; +wire ByteCntEq5; +wire ByteCntEq6; +wire ByteCntEq7; +wire ByteCntSmall7; +wire [31:0] Crc; +wire Enable_Crc; +wire Initialize_Crc; +wire [3:0] Data_Crc; +wire GenerateRxValid; +wire GenerateRxStartFrm; +wire GenerateRxEndFrm; +wire DribbleRxEndFrm; +wire [3:0] DlyCrcCnt; +wire IFGCounterEq24; + +assign MRxDEqD = MRxD == 4'hd; +assign MRxDEq5 = MRxD == 4'h5; + + +// Rx State Machine module +eth_rxstatem rxstatem1 (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .ByteCntEq0(ByteCntEq0), + .ByteCntGreat2(ByteCntGreat2), .Transmitting(Transmitting), .MRxDEq5(MRxDEq5), + .MRxDEqD(MRxDEqD), .IFGCounterEq24(IFGCounterEq24), .ByteCntMaxFrame(ByteCntMaxFrame), + .StateData(StateData), .StateIdle(StateIdle), .StatePreamble(StatePreamble), + .StateSFD(StateSFD), .StateDrop(StateDrop) + ); + + +// Rx Counters module +eth_rxcounters rxcounters1 (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .StateIdle(StateIdle), + .StateSFD(StateSFD), .StateData(StateData), .StateDrop(StateDrop), + .StatePreamble(StatePreamble), .MRxDEqD(MRxDEqD), .DlyCrcEn(DlyCrcEn), + .DlyCrcCnt(DlyCrcCnt), .Transmitting(Transmitting), .MaxFL(MaxFL), .r_IFG(r_IFG), + .HugEn(HugEn), .IFGCounterEq24(IFGCounterEq24), .ByteCntEq0(ByteCntEq0), + .ByteCntEq1(ByteCntEq1), .ByteCntEq2(ByteCntEq2), .ByteCntEq3(ByteCntEq3), + .ByteCntEq4(ByteCntEq4), .ByteCntEq5(ByteCntEq5), .ByteCntEq6(ByteCntEq6), + .ByteCntEq7(ByteCntEq7), .ByteCntGreat2(ByteCntGreat2), + .ByteCntSmall7(ByteCntSmall7), .ByteCntMaxFrame(ByteCntMaxFrame), + .ByteCntOut(ByteCnt) + ); + +// Rx Address Check + +eth_rxaddrcheck rxaddrcheck1 + (.MRxClk(MRxClk), .Reset( Reset), .RxData(RxData), + .Broadcast (Broadcast), .r_Bro (r_Bro), .r_Pro(r_Pro), + .ByteCntEq6(ByteCntEq6), .ByteCntEq7(ByteCntEq7), .ByteCntEq2(ByteCntEq2), + .ByteCntEq3(ByteCntEq3), .ByteCntEq4(ByteCntEq4), .ByteCntEq5(ByteCntEq5), + .HASH0(r_HASH0), .HASH1(r_HASH1), + .CrcHash(CrcHash), .CrcHashGood(CrcHashGood), .StateData(StateData), + .Multicast(Multicast), .MAC(MAC), .RxAbort(RxAbort), + .RxEndFrm(RxEndFrm), .AddressMiss(AddressMiss), .PassAll(PassAll), + .ControlFrmAddressOK(ControlFrmAddressOK) + ); + + +assign Enable_Crc = MRxDV & (|StateData & ~ByteCntMaxFrame); +assign Initialize_Crc = StateSFD | DlyCrcEn & (|DlyCrcCnt[3:0]) & DlyCrcCnt[3:0] < 4'h9; + +assign Data_Crc[0] = MRxD[3]; +assign Data_Crc[1] = MRxD[2]; +assign Data_Crc[2] = MRxD[1]; +assign Data_Crc[3] = MRxD[0]; + + +// Connecting module Crc +eth_crc crcrx (.Clk(MRxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc), + .Crc(Crc), .CrcError(CrcError) + ); + + + +// Latching CRC for use in the hash table + +always @ (posedge MRxClk) +begin + CrcHashGood <= #Tp StateData[0] & ByteCntEq6; +end + +always @ (posedge MRxClk) +begin + if(Reset | StateIdle) + CrcHash[5:0] <= #Tp 6'h0; + else + if(StateData[0] & ByteCntEq6) + CrcHash[5:0] <= #Tp Crc[31:26]; +end + + +// Output byte stream +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + RxData_d[7:0] <= #Tp 8'h0; + DelayData <= #Tp 1'b0; + LatchedByte[7:0] <= #Tp 8'h0; + RxData[7:0] <= #Tp 8'h0; + end + else + begin + LatchedByte[7:0] <= #Tp {MRxD[3:0], LatchedByte[7:4]}; // Latched byte + DelayData <= #Tp StateData[0]; + + if(GenerateRxValid) + RxData_d[7:0] <= #Tp LatchedByte[7:0] & {8{|StateData}}; // Data goes through only in data state + else + if(~DelayData) + RxData_d[7:0] <= #Tp 8'h0; // Delaying data to be valid for two cycles. Zero when not active. + + RxData[7:0] <= #Tp RxData_d[7:0]; // Output data byte + end +end + + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + Broadcast <= #Tp 1'b0; + else + begin + if(StateData[0] & ~(&LatchedByte[7:0]) & ByteCntSmall7) + Broadcast <= #Tp 1'b0; + else + if(StateData[0] & (&LatchedByte[7:0]) & ByteCntEq1) + Broadcast <= #Tp 1'b1; + else + if(RxAbort | RxEndFrm) + Broadcast <= #Tp 1'b0; + end +end + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + Multicast <= #Tp 1'b0; + else + begin + if(StateData[0] & ByteCntEq1 & LatchedByte[0]) + Multicast <= #Tp 1'b1; + else if(RxAbort | RxEndFrm) + Multicast <= #Tp 1'b0; + end +end + + +assign GenerateRxValid = StateData[0] & (~ByteCntEq0 | DlyCrcCnt >= 4'h3); + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + RxValid_d <= #Tp 1'b0; + RxValid <= #Tp 1'b0; + end + else + begin + RxValid_d <= #Tp GenerateRxValid; + RxValid <= #Tp RxValid_d; + end +end + + +assign GenerateRxStartFrm = StateData[0] & (ByteCntEq1 & ~DlyCrcEn | DlyCrcCnt == 4'h3 & DlyCrcEn); + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + RxStartFrm_d <= #Tp 1'b0; + RxStartFrm <= #Tp 1'b0; + end + else + begin + RxStartFrm_d <= #Tp GenerateRxStartFrm; + RxStartFrm <= #Tp RxStartFrm_d; + end +end + + +assign GenerateRxEndFrm = StateData[0] & (~MRxDV & ByteCntGreat2 | ByteCntMaxFrame); +assign DribbleRxEndFrm = StateData[1] & ~MRxDV & ByteCntGreat2; + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + RxEndFrm_d <= #Tp 1'b0; + RxEndFrm <= #Tp 1'b0; + end + else + begin + RxEndFrm_d <= #Tp GenerateRxEndFrm; + RxEndFrm <= #Tp RxEndFrm_d | DribbleRxEndFrm; + end +end + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v new file mode 100644 index 000000000..783dfe6a4 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v @@ -0,0 +1,200 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_rxstatem.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_rxstatem.v,v $ +// Revision 1.6 2002/11/13 22:28:26 tadejm +// StartIdle state changed (not important the size of the packet). +// StartData1 activates only while ByteCnt is smaller than the MaxFrame. +// +// Revision 1.5 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.4 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.3 2001/10/18 12:07:11 mohor +// Status signals changed, Adress decoding changed, interrupt controller +// added. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.2 2001/07/03 12:55:41 mohor +// Minor changes because of the synthesys warnings. +// +// +// Revision 1.1 2001/06/27 21:26:19 mohor +// Initial release of the RxEthMAC module. +// +// +// +// + + +`include "timescale.v" + + +module eth_rxstatem (MRxClk, Reset, MRxDV, ByteCntEq0, ByteCntGreat2, Transmitting, MRxDEq5, MRxDEqD, + IFGCounterEq24, ByteCntMaxFrame, StateData, StateIdle, StatePreamble, StateSFD, + StateDrop + ); + +parameter Tp = 1; + +input MRxClk; +input Reset; +input MRxDV; +input ByteCntEq0; +input ByteCntGreat2; +input MRxDEq5; +input Transmitting; +input MRxDEqD; +input IFGCounterEq24; +input ByteCntMaxFrame; + +output [1:0] StateData; +output StateIdle; +output StateDrop; +output StatePreamble; +output StateSFD; + +reg StateData0; +reg StateData1; +reg StateIdle; +reg StateDrop; +reg StatePreamble; +reg StateSFD; + +wire StartIdle; +wire StartDrop; +wire StartData0; +wire StartData1; +wire StartPreamble; +wire StartSFD; + + +// Defining the next state +assign StartIdle = ~MRxDV & (StateDrop | StatePreamble | StateSFD | (|StateData)); + +assign StartPreamble = MRxDV & ~MRxDEq5 & (StateIdle & ~Transmitting); + +assign StartSFD = MRxDV & MRxDEq5 & (StateIdle & ~Transmitting | StatePreamble); + +assign StartData0 = MRxDV & (StateSFD & MRxDEqD & IFGCounterEq24 | StateData1); + +assign StartData1 = MRxDV & StateData0 & (~ByteCntMaxFrame); + +assign StartDrop = MRxDV & (StateIdle & Transmitting | StateSFD & ~IFGCounterEq24 & MRxDEqD + | StateData0 & ByteCntMaxFrame + ); + +// Rx State Machine +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + StateIdle <= #Tp 1'b0; + StateDrop <= #Tp 1'b1; + StatePreamble <= #Tp 1'b0; + StateSFD <= #Tp 1'b0; + StateData0 <= #Tp 1'b0; + StateData1 <= #Tp 1'b0; + end + else + begin + if(StartPreamble | StartSFD | StartDrop) + StateIdle <= #Tp 1'b0; + else + if(StartIdle) + StateIdle <= #Tp 1'b1; + + if(StartIdle) + StateDrop <= #Tp 1'b0; + else + if(StartDrop) + StateDrop <= #Tp 1'b1; + + if(StartSFD | StartIdle | StartDrop) + StatePreamble <= #Tp 1'b0; + else + if(StartPreamble) + StatePreamble <= #Tp 1'b1; + + if(StartPreamble | StartIdle | StartData0 | StartDrop) + StateSFD <= #Tp 1'b0; + else + if(StartSFD) + StateSFD <= #Tp 1'b1; + + if(StartIdle | StartData1 | StartDrop) + StateData0 <= #Tp 1'b0; + else + if(StartData0) + StateData0 <= #Tp 1'b1; + + if(StartIdle | StartData0 | StartDrop) + StateData1 <= #Tp 1'b0; + else + if(StartData1) + StateData1 <= #Tp 1'b1; + end +end + +assign StateData[1:0] = {StateData1, StateData0}; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v new file mode 100644 index 000000000..9a9ef66ea --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v @@ -0,0 +1,154 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_shiftreg.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_shiftreg.v,v $ +// Revision 1.6 2005/03/08 14:45:09 igorm +// Case statement improved for synthesys. +// +// Revision 1.5 2002/08/14 18:16:59 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.4 2002/03/02 21:06:01 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`include "timescale.v" + + +module eth_shiftreg(Clk, Reset, MdcEn_n, Mdi, Fiad, Rgad, CtrlData, WriteOp, ByteSelect, + LatchByte, ShiftedBit, Prsd, LinkFail); + + +parameter Tp=1; + +input Clk; // Input clock (Host clock) +input Reset; // Reset signal +input MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. +input Mdi; // MII input data +input [4:0] Fiad; // PHY address +input [4:0] Rgad; // Register address (within the selected PHY) +input [15:0]CtrlData; // Control data (data to be written to the PHY) +input WriteOp; // The current operation is a PHY register write operation +input [3:0] ByteSelect; // Byte select +input [1:0] LatchByte; // Byte select for latching (read operation) + +output ShiftedBit; // Bit shifted out of the shift register +output[15:0]Prsd; // Read Status Data (data read from the PHY) +output LinkFail; // Link Integrity Signal + +reg [7:0] ShiftReg; // Shift register for shifting the data in and out +reg [15:0]Prsd; +reg LinkFail; + + + + +// ShiftReg[7:0] :: Shift Register Data +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + ShiftReg[7:0] <= #Tp 8'h0; + Prsd[15:0] <= #Tp 16'h0; + LinkFail <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + if(|ByteSelect) + begin + case (ByteSelect[3:0]) // synopsys parallel_case full_case + 4'h1 : ShiftReg[7:0] <= #Tp {2'b01, ~WriteOp, WriteOp, Fiad[4:1]}; + 4'h2 : ShiftReg[7:0] <= #Tp {Fiad[0], Rgad[4:0], 2'b10}; + 4'h4 : ShiftReg[7:0] <= #Tp CtrlData[15:8]; + 4'h8 : ShiftReg[7:0] <= #Tp CtrlData[7:0]; + endcase + end + else + begin + ShiftReg[7:0] <= #Tp {ShiftReg[6:0], Mdi}; + if(LatchByte[0]) + begin + Prsd[7:0] <= #Tp {ShiftReg[6:0], Mdi}; + if(Rgad == 5'h01) + LinkFail <= #Tp ~ShiftReg[1]; // this is bit [2], because it is not shifted yet + end + else + begin + if(LatchByte[1]) + Prsd[15:8] <= #Tp {ShiftReg[6:0], Mdi}; + end + end + end + end +end + + +assign ShiftedBit = ShiftReg[7]; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v new file mode 100644 index 000000000..f1de63a6d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v @@ -0,0 +1,312 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_spram_256x32.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_spram_256x32.v,v $ +// Revision 1.10 2005/02/21 12:48:07 igorm +// Warning fixes. +// +// Revision 1.9 2003/12/05 12:43:06 tadejm +// Corrected address mismatch for xilinx RAMB4_S8 model which has wider address than RAMB4_S16. +// +// Revision 1.8 2003/12/04 14:59:13 simons +// Lapsus fixed (!we -> ~we). +// +// Revision 1.7 2003/11/12 18:24:59 tadejm +// WISHBONE slave changed and tested from only 32-bit accesss to byte access. +// +// Revision 1.6 2003/10/17 07:46:15 markom +// mbist signals updated according to newest convention +// +// Revision 1.5 2003/08/14 16:42:58 simons +// Artisan ram instance added. +// +// Revision 1.4 2002/10/18 17:04:20 tadejm +// Changed BIST scan signals. +// +// Revision 1.3 2002/10/10 16:29:30 mohor +// BIST added. +// +// Revision 1.2 2002/09/23 18:24:31 mohor +// ETH_VIRTUAL_SILICON_RAM supported (for ASIC implementation). +// +// Revision 1.1 2002/07/23 16:36:09 mohor +// ethernet spram added. So far a generic ram and xilinx RAMB4 are used. +// +// +// + +`include "eth_defines.v" +`include "timescale.v" + +module eth_spram_256x32( + // Generic synchronous single-port RAM interface + clk, rst, ce, we, oe, addr, di, do + +`ifdef ETH_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif + + + +); + + // + // Generic synchronous single-port RAM interface + // + input clk; // Clock, rising edge + input rst; // Reset, active high + input ce; // Chip enable input, active high + input [3:0] we; // Write enable input, active high + input oe; // Output enable input, active high + input [7:0] addr; // address bus inputs + input [31:0] di; // input data bus + output [31:0] do; // output data bus + + +`ifdef ETH_BIST + input mbist_si_i; // bist scan serial in + output mbist_so_o; // bist scan serial out + input [`ETH_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +`ifdef ETH_XILINX_RAMB4 + + /*RAMB4_S16 ram0 + ( + .DO (do[15:0]), + .ADDR (addr), + .DI (di[15:0]), + .EN (ce), + .CLK (clk), + .WE (we), + .RST (rst) + ); + + RAMB4_S16 ram1 + ( + .DO (do[31:16]), + .ADDR (addr), + .DI (di[31:16]), + .EN (ce), + .CLK (clk), + .WE (we), + .RST (rst) + );*/ + + RAMB4_S8 ram0 + ( + .DO (do[7:0]), + .ADDR ({1'b0, addr}), + .DI (di[7:0]), + .EN (ce), + .CLK (clk), + .WE (we[0]), + .RST (rst) + ); + + RAMB4_S8 ram1 + ( + .DO (do[15:8]), + .ADDR ({1'b0, addr}), + .DI (di[15:8]), + .EN (ce), + .CLK (clk), + .WE (we[1]), + .RST (rst) + ); + + RAMB4_S8 ram2 + ( + .DO (do[23:16]), + .ADDR ({1'b0, addr}), + .DI (di[23:16]), + .EN (ce), + .CLK (clk), + .WE (we[2]), + .RST (rst) + ); + + RAMB4_S8 ram3 + ( + .DO (do[31:24]), + .ADDR ({1'b0, addr}), + .DI (di[31:24]), + .EN (ce), + .CLK (clk), + .WE (we[3]), + .RST (rst) + ); + +`else // !ETH_XILINX_RAMB4 +`ifdef ETH_VIRTUAL_SILICON_RAM + `ifdef ETH_BIST + //vs_hdsp_256x32_bist ram0_bist + vs_hdsp_256x32_bw_bist ram0_bist + `else + //vs_hdsp_256x32 ram0 + vs_hdsp_256x32_bw ram0 + `endif + ( + .CK (clk), + .CEN (!ce), + .WEN (~we), + .OEN (!oe), + .ADR (addr), + .DI (di), + .DOUT (do) + + `ifdef ETH_BIST + , + // debug chain signals + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) + `endif + ); + +`else // !ETH_VIRTUAL_SILICON_RAM + +`ifdef ETH_ARTISAN_RAM + `ifdef ETH_BIST + //art_hssp_256x32_bist ram0_bist + art_hssp_256x32_bw_bist ram0_bist + `else + //art_hssp_256x32 ram0 + art_hssp_256x32_bw ram0 + `endif + ( + .CLK (clk), + .CEN (!ce), + .WEN (~we), + .OEN (!oe), + .A (addr), + .D (di), + .Q (do) + + `ifdef ETH_BIST + , + // debug chain signals + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) + `endif + ); + +`else // !ETH_ARTISAN_RAM +`ifdef ETH_ALTERA_ALTSYNCRAM + + altera_spram_256x32 altera_spram_256x32_inst + ( + .address (addr), + .wren (ce & we), + .clock (clk), + .data (di), + .q (do) + ); //exemplar attribute altera_spram_256x32_inst NOOPT TRUE + +`else // !ETH_ALTERA_ALTSYNCRAM + + + // + // Generic single-port synchronous RAM model + // + + // + // Generic RAM's registers and wires + // + reg [ 7: 0] mem0 [255:0]; // RAM content + reg [15: 8] mem1 [255:0]; // RAM content + reg [23:16] mem2 [255:0]; // RAM content + reg [31:24] mem3 [255:0]; // RAM content + wire [31:0] q; // RAM output + reg [7:0] raddr; // RAM read address + // + // Data output drivers + // + assign do = (oe & ce) ? q : {32{1'bz}}; + + // + // RAM read and write + // + + // read operation + always@(posedge clk) + if (ce) // && !we) + raddr <= #1 addr; // read address needs to be registered to read clock + + assign #1 q = rst ? {32{1'b0}} : {mem3[raddr], mem2[raddr], mem1[raddr], mem0[raddr]}; + + // write operation + always@(posedge clk) + begin + if (ce && we[3]) + mem3[addr] <= #1 di[31:24]; + if (ce && we[2]) + mem2[addr] <= #1 di[23:16]; + if (ce && we[1]) + mem1[addr] <= #1 di[15: 8]; + if (ce && we[0]) + mem0[addr] <= #1 di[ 7: 0]; + end + + // Task prints range of memory + // *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations. + task print_ram; + input [7:0] start; + input [7:0] finish; + integer rnum; + begin + for (rnum=start;rnum<=finish;rnum=rnum+1) + $display("Addr %h = %0h %0h %0h %0h",rnum,mem3[rnum],mem2[rnum],mem1[rnum],mem0[rnum]); + end + endtask + +`endif // !ETH_ALTERA_ALTSYNCRAM +`endif // !ETH_ARTISAN_RAM +`endif // !ETH_VIRTUAL_SILICON_RAM +`endif // !ETH_XILINX_RAMB4 + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v new file mode 100644 index 000000000..17185b2c7 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v @@ -0,0 +1,971 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_top.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_top.v,v $ +// Revision 1.52 2005/03/21 20:07:18 igorm +// Some small fixes + some troubles fixed. +// +// Revision 1.51 2005/02/21 11:13:17 igorm +// Defer indication fixed. +// +// Revision 1.50 2004/04/26 15:26:23 igorm +// - Bug connected to the TX_BD_NUM_Wr signal fixed (bug came in with the +// previous update of the core. +// - TxBDAddress is set to 0 after the TX is enabled in the MODER register. +// - RxBDAddress is set to r_TxBDNum<<1 after the RX is enabled in the MODER +// register. (thanks to Mathias and Torbjorn) +// - Multicast reception was fixed. Thanks to Ulrich Gries +// +// Revision 1.49 2003/11/12 18:24:59 tadejm +// WISHBONE slave changed and tested from only 32-bit accesss to byte access. +// +// Revision 1.48 2003/10/17 07:46:16 markom +// mbist signals updated according to newest convention +// +// Revision 1.47 2003/10/06 15:43:45 knguyen +// Update RxEnSync only when mrxdv_pad_i is inactive (LOW). +// +// Revision 1.46 2003/01/30 13:30:22 tadejm +// Defer indication changed. +// +// Revision 1.45 2003/01/22 13:49:26 tadejm +// When control packets were received, they were ignored in some cases. +// +// Revision 1.44 2003/01/21 12:09:40 mohor +// When receiving normal data frame and RxFlow control was switched on, RXB +// interrupt was not set. +// +// Revision 1.43 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.42 2002/11/21 00:09:19 mohor +// TPauseRq synchronized to tx_clk. +// +// Revision 1.41 2002/11/19 18:13:49 mohor +// r_MiiMRst is not used for resetting the MIIM module. wb_rst used instead. +// +// Revision 1.40 2002/11/19 17:34:25 mohor +// AddressMiss status is connecting to the Rx BD. AddressMiss is identifying +// that a frame was received because of the promiscous mode. +// +// Revision 1.39 2002/11/18 17:31:55 mohor +// wb_rst_i is used for MIIM reset. +// +// Revision 1.38 2002/11/14 18:37:20 mohor +// r_Rst signal does not reset any module any more and is removed from the design. +// +// Revision 1.37 2002/11/13 22:25:36 tadejm +// All modules are reset with wb_rst instead of the r_Rst. Exception is MII module. +// +// Revision 1.36 2002/10/18 17:04:20 tadejm +// Changed BIST scan signals. +// +// Revision 1.35 2002/10/11 13:36:58 mohor +// Typo error fixed. (When using Bist) +// +// Revision 1.34 2002/10/10 16:49:50 mohor +// Signals for WISHBONE B3 compliant interface added. +// +// Revision 1.33 2002/10/10 16:29:30 mohor +// BIST added. +// +// Revision 1.32 2002/09/20 17:12:58 mohor +// CsMiss added. When address between 0x800 and 0xfff is accessed within +// Ethernet Core, error acknowledge is generated. +// +// Revision 1.31 2002/09/12 14:50:17 mohor +// CarrierSenseLost bug fixed when operating in full duplex mode. +// +// Revision 1.30 2002/09/10 10:35:23 mohor +// Ethernet debug registers removed. +// +// Revision 1.29 2002/09/09 13:03:13 mohor +// Error acknowledge is generated when accessing BDs and RST bit in the +// MODER register (r_Rst) is set. +// +// Revision 1.28 2002/09/04 18:44:10 mohor +// Signals related to the control frames connected. Debug registers reg1, 2, 3, 4 +// connected. +// +// Revision 1.27 2002/07/25 18:15:37 mohor +// RxAbort changed. Packets received with MRxErr (from PHY) are also +// aborted. +// +// Revision 1.26 2002/07/17 18:51:50 mohor +// EXTERNAL_DMA removed. External DMA not supported. +// +// Revision 1.25 2002/05/03 10:15:50 mohor +// Outputs registered. Reset changed for eth_wishbone module. +// +// Revision 1.24 2002/04/22 14:15:42 mohor +// Wishbone signals are registered when ETH_REGISTERED_OUTPUTS is +// selected in eth_defines.v +// +// Revision 1.23 2002/03/25 13:33:53 mohor +// md_padoen_o changed to md_padoe_o. Signal was always active high, just +// name was incorrect. +// +// Revision 1.22 2002/02/26 16:59:54 mohor +// Small fixes for external/internal DMA missmatches. +// +// Revision 1.21 2002/02/26 16:21:00 mohor +// Interrupts changed in the top file +// +// Revision 1.20 2002/02/18 10:40:17 mohor +// Small fixes. +// +// Revision 1.19 2002/02/16 14:03:44 mohor +// Registered trimmed. Unused registers removed. +// +// Revision 1.18 2002/02/16 13:06:33 mohor +// EXTERNAL_DMA used instead of WISHBONE_DMA. +// +// Revision 1.17 2002/02/16 07:15:27 mohor +// Testbench fixed, code simplified, unused signals removed. +// +// Revision 1.16 2002/02/15 13:49:39 mohor +// RxAbort is connected differently. +// +// Revision 1.15 2002/02/15 11:38:26 mohor +// Changes that were lost when updating from 1.11 to 1.14 fixed. +// +// Revision 1.14 2002/02/14 20:19:11 billditt +// Modified for Address Checking, +// addition of eth_addrcheck.v +// +// Revision 1.13 2002/02/12 17:03:03 mohor +// HASH0 and HASH1 registers added. Registers address width was +// changed to 8 bits. +// +// Revision 1.12 2002/02/11 09:18:22 mohor +// Tx status is written back to the BD. +// +// Revision 1.11 2002/02/08 16:21:54 mohor +// Rx status is written back to the BD. +// +// Revision 1.10 2002/02/06 14:10:21 mohor +// non-DMA host interface added. Select the right configutation in eth_defines. +// +// Revision 1.9 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.8 2001/12/05 15:00:16 mohor +// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors +// instead of the number of RX descriptors). +// +// Revision 1.7 2001/12/05 10:45:59 mohor +// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead. +// +// Revision 1.6 2001/10/19 11:24:29 mohor +// Number of addresses (wb_adr_i) minimized. +// +// Revision 1.5 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.4 2001/10/18 12:07:11 mohor +// Status signals changed, Adress decoding changed, interrupt controller +// added. +// +// Revision 1.3 2001/09/24 15:02:56 mohor +// Defines changed (All precede with ETH_). Small changes because some +// tools generate warnings when two operands are together. Synchronization +// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC +// demands). +// +// Revision 1.2 2001/08/15 14:03:59 mohor +// Signal names changed on the top level for easier pad insertion (ASIC). +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.2 2001/08/02 09:25:31 mohor +// Unconnected signals are now connected. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// +// +// + + +`include "eth_defines.v" +`include "timescale.v" + + +module eth_top +( + // WISHBONE common + wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o, + + // WISHBONE slave + wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, wb_err_o, + + // WISHBONE master + m_wb_adr_o, m_wb_sel_o, m_wb_we_o, + m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o, + m_wb_stb_o, m_wb_ack_i, m_wb_err_i, + +`ifdef ETH_WISHBONE_B3 + m_wb_cti_o, m_wb_bte_o, +`endif + + //TX + mtx_clk_pad_i, mtxd_pad_o, mtxen_pad_o, mtxerr_pad_o, + + //RX + mrx_clk_pad_i, mrxd_pad_i, mrxdv_pad_i, mrxerr_pad_i, mcoll_pad_i, mcrs_pad_i, + + // MIIM + mdc_pad_o, md_pad_i, md_pad_o, md_padoe_o, + + int_o + + // Bist +`ifdef ETH_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif + +); + + +parameter Tp = 1; + + +// WISHBONE common +input wb_clk_i; // WISHBONE clock +input wb_rst_i; // WISHBONE reset +input [31:0] wb_dat_i; // WISHBONE data input +output [31:0] wb_dat_o; // WISHBONE data output +output wb_err_o; // WISHBONE error output + +// WISHBONE slave +input [11:2] wb_adr_i; // WISHBONE address input +input [3:0] wb_sel_i; // WISHBONE byte select input +input wb_we_i; // WISHBONE write enable input +input wb_cyc_i; // WISHBONE cycle input +input wb_stb_i; // WISHBONE strobe input +output wb_ack_o; // WISHBONE acknowledge output + +// WISHBONE master +output [31:0] m_wb_adr_o; +output [3:0] m_wb_sel_o; +output m_wb_we_o; +input [31:0] m_wb_dat_i; +output [31:0] m_wb_dat_o; +output m_wb_cyc_o; +output m_wb_stb_o; +input m_wb_ack_i; +input m_wb_err_i; + +wire [29:0] m_wb_adr_tmp; + +`ifdef ETH_WISHBONE_B3 +output [2:0] m_wb_cti_o; // Cycle Type Identifier +output [1:0] m_wb_bte_o; // Burst Type Extension +`endif + +// Tx +input mtx_clk_pad_i; // Transmit clock (from PHY) +output [3:0] mtxd_pad_o; // Transmit nibble (to PHY) +output mtxen_pad_o; // Transmit enable (to PHY) +output mtxerr_pad_o; // Transmit error (to PHY) + +// Rx +input mrx_clk_pad_i; // Receive clock (from PHY) +input [3:0] mrxd_pad_i; // Receive nibble (from PHY) +input mrxdv_pad_i; // Receive data valid (from PHY) +input mrxerr_pad_i; // Receive data error (from PHY) + +// Common Tx and Rx +input mcoll_pad_i; // Collision (from PHY) +input mcrs_pad_i; // Carrier sense (from PHY) + +// MII Management interface +input md_pad_i; // MII data input (from I/O cell) +output mdc_pad_o; // MII Management data clock (to PHY) +output md_pad_o; // MII data output (to I/O cell) +output md_padoe_o; // MII data output enable (to I/O cell) + +output int_o; // Interrupt output + +// Bist +`ifdef ETH_BIST +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`ETH_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +wire [7:0] r_ClkDiv; +wire r_MiiNoPre; +wire [15:0] r_CtrlData; +wire [4:0] r_FIAD; +wire [4:0] r_RGAD; +wire r_WCtrlData; +wire r_RStat; +wire r_ScanStat; +wire NValid_stat; +wire Busy_stat; +wire LinkFail; +wire [15:0] Prsd; // Read Status Data (data read from the PHY) +wire WCtrlDataStart; +wire RStatStart; +wire UpdateMIIRX_DATAReg; + +wire TxStartFrm; +wire TxEndFrm; +wire TxUsedData; +wire [7:0] TxData; +wire TxRetry; +wire TxAbort; +wire TxUnderRun; +wire TxDone; + + +reg WillSendControlFrame_sync1; +reg WillSendControlFrame_sync2; +reg WillSendControlFrame_sync3; +reg RstTxPauseRq; + +reg TxPauseRq_sync1; +reg TxPauseRq_sync2; +reg TxPauseRq_sync3; +reg TPauseRq; + + +// Connecting Miim module +eth_miim miim1 +( + .Clk(wb_clk_i), .Reset(wb_rst_i), .Divider(r_ClkDiv), + .NoPre(r_MiiNoPre), .CtrlData(r_CtrlData), .Rgad(r_RGAD), + .Fiad(r_FIAD), .WCtrlData(r_WCtrlData), .RStat(r_RStat), + .ScanStat(r_ScanStat), .Mdi(md_pad_i), .Mdo(md_pad_o), + .MdoEn(md_padoe_o), .Mdc(mdc_pad_o), .Busy(Busy_stat), + .Prsd(Prsd), .LinkFail(LinkFail), .Nvalid(NValid_stat), + .WCtrlDataStart(WCtrlDataStart), .RStatStart(RStatStart), .UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg) +); + + + + +wire [3:0] RegCs; // Connected to registers +wire [31:0] RegDataOut; // Multiplexed to wb_dat_o +wire r_RecSmall; // Receive small frames +wire r_LoopBck; // Loopback +wire r_TxEn; // Tx Enable +wire r_RxEn; // Rx Enable + +wire MRxDV_Lb; // Muxed MII receive data valid +wire MRxErr_Lb; // Muxed MII Receive Error +wire [3:0] MRxD_Lb; // Muxed MII Receive Data +wire Transmitting; // Indication that TxEthMAC is transmitting +wire r_HugEn; // Huge packet enable +wire r_DlyCrcEn; // Delayed CRC enabled +wire [15:0] r_MaxFL; // Maximum frame length + +wire [15:0] r_MinFL; // Minimum frame length +wire ShortFrame; +wire DribbleNibble; // Extra nibble received +wire ReceivedPacketTooBig; // Received packet is too big +wire [47:0] r_MAC; // MAC address +wire LoadRxStatus; // Rx status was loaded +wire [31:0] r_HASH0; // HASH table, lower 4 bytes +wire [31:0] r_HASH1; // HASH table, upper 4 bytes +wire [7:0] r_TxBDNum; // Receive buffer descriptor number +wire [6:0] r_IPGT; // +wire [6:0] r_IPGR1; // +wire [6:0] r_IPGR2; // +wire [5:0] r_CollValid; // +wire [15:0] r_TxPauseTV; // Transmit PAUSE value +wire r_TxPauseRq; // Transmit PAUSE request + +wire [3:0] r_MaxRet; // +wire r_NoBckof; // +wire r_ExDfrEn; // +wire r_TxFlow; // Tx flow control enable +wire r_IFG; // Minimum interframe gap for incoming packets + +wire TxB_IRQ; // Interrupt Tx Buffer +wire TxE_IRQ; // Interrupt Tx Error +wire RxB_IRQ; // Interrupt Rx Buffer +wire RxE_IRQ; // Interrupt Rx Error +wire Busy_IRQ; // Interrupt Busy (lack of buffers) + +//wire DWord; +wire ByteSelected; +wire BDAck; +wire [31:0] BD_WB_DAT_O; // wb_dat_o that comes from the Wishbone module (for buffer descriptors read/write) +wire [3:0] BDCs; // Buffer descriptor CS +wire CsMiss; // When access to the address between 0x800 and 0xfff occurs, acknowledge is set + // but data is not valid. +wire r_Pad; +wire r_CrcEn; +wire r_FullD; +wire r_Pro; +wire r_Bro; +wire r_NoPre; +wire r_RxFlow; +wire r_PassAll; +wire TxCtrlEndFrm; +wire StartTxDone; +wire SetPauseTimer; +wire TxUsedDataIn; +wire TxDoneIn; +wire TxAbortIn; +wire PerPacketPad; +wire PadOut; +wire PerPacketCrcEn; +wire CrcEnOut; +wire TxStartFrmOut; +wire TxEndFrmOut; +wire ReceivedPauseFrm; +wire ControlFrmAddressOK; +wire RxStatusWriteLatched_sync2; +wire LateCollision; +wire DeferIndication; +wire LateCollLatched; +wire DeferLatched; +wire RstDeferLatched; +wire CarrierSenseLost; + +wire temp_wb_ack_o; +wire [31:0] temp_wb_dat_o; +wire temp_wb_err_o; + +`ifdef ETH_REGISTERED_OUTPUTS + reg temp_wb_ack_o_reg; + reg [31:0] temp_wb_dat_o_reg; + reg temp_wb_err_o_reg; +`endif + +//assign DWord = &wb_sel_i; +assign ByteSelected = |wb_sel_i; +assign RegCs[3] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & ~wb_adr_i[10] & wb_sel_i[3]; // 0x0 - 0x3FF +assign RegCs[2] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & ~wb_adr_i[10] & wb_sel_i[2]; // 0x0 - 0x3FF +assign RegCs[1] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & ~wb_adr_i[10] & wb_sel_i[1]; // 0x0 - 0x3FF +assign RegCs[0] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & ~wb_adr_i[10] & wb_sel_i[0]; // 0x0 - 0x3FF +assign BDCs[3] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & wb_adr_i[10] & wb_sel_i[3]; // 0x400 - 0x7FF +assign BDCs[2] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & wb_adr_i[10] & wb_sel_i[2]; // 0x400 - 0x7FF +assign BDCs[1] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & wb_adr_i[10] & wb_sel_i[1]; // 0x400 - 0x7FF +assign BDCs[0] = wb_stb_i & wb_cyc_i & ByteSelected & ~wb_adr_i[11] & wb_adr_i[10] & wb_sel_i[0]; // 0x400 - 0x7FF +assign CsMiss = wb_stb_i & wb_cyc_i & ByteSelected & wb_adr_i[11]; // 0x800 - 0xfFF +assign temp_wb_dat_o = ((|RegCs) & ~wb_we_i)? RegDataOut : BD_WB_DAT_O; +assign temp_wb_err_o = wb_stb_i & wb_cyc_i & (~ByteSelected | CsMiss); + +`ifdef ETH_REGISTERED_OUTPUTS + assign wb_ack_o = temp_wb_ack_o_reg; + assign wb_dat_o[31:0] = temp_wb_dat_o_reg; + assign wb_err_o = temp_wb_err_o_reg; +`else + assign wb_ack_o = temp_wb_ack_o; + assign wb_dat_o[31:0] = temp_wb_dat_o; + assign wb_err_o = temp_wb_err_o; +`endif + +`ifdef ETH_AVALON_BUS + // As Avalon has no corresponding "error" signal, I (erroneously) will + // send an ack to Avalon, even when accessing undefined memory. This + // is a grey area in Avalon vs. Wishbone specs: My understanding + // is that Avalon expects all memory addressable by the addr bus feeding + // a slave to be, at the very minimum, readable. + assign temp_wb_ack_o = (|RegCs) | BDAck | CsMiss; +`else // WISHBONE + assign temp_wb_ack_o = (|RegCs) | BDAck; +`endif + +`ifdef ETH_REGISTERED_OUTPUTS + always @ (posedge wb_clk_i or posedge wb_rst_i) + begin + if(wb_rst_i) + begin + temp_wb_ack_o_reg <=#Tp 1'b0; + temp_wb_dat_o_reg <=#Tp 32'h0; + temp_wb_err_o_reg <=#Tp 1'b0; + end + else + begin + temp_wb_ack_o_reg <=#Tp temp_wb_ack_o & ~temp_wb_ack_o_reg; + temp_wb_dat_o_reg <=#Tp temp_wb_dat_o; + temp_wb_err_o_reg <=#Tp temp_wb_err_o & ~temp_wb_err_o_reg; + end + end +`endif + + +// Connecting Ethernet registers +eth_registers ethreg1 +( + .DataIn(wb_dat_i), .Address(wb_adr_i[9:2]), .Rw(wb_we_i), + .Cs(RegCs), .Clk(wb_clk_i), .Reset(wb_rst_i), + .DataOut(RegDataOut), .r_RecSmall(r_RecSmall), + .r_Pad(r_Pad), .r_HugEn(r_HugEn), .r_CrcEn(r_CrcEn), + .r_DlyCrcEn(r_DlyCrcEn), .r_FullD(r_FullD), + .r_ExDfrEn(r_ExDfrEn), .r_NoBckof(r_NoBckof), .r_LoopBck(r_LoopBck), + .r_IFG(r_IFG), .r_Pro(r_Pro), .r_Iam(), + .r_Bro(r_Bro), .r_NoPre(r_NoPre), .r_TxEn(r_TxEn), + .r_RxEn(r_RxEn), .Busy_IRQ(Busy_IRQ), .RxE_IRQ(RxE_IRQ), + .RxB_IRQ(RxB_IRQ), .TxE_IRQ(TxE_IRQ), .TxB_IRQ(TxB_IRQ), + .r_IPGT(r_IPGT), + .r_IPGR1(r_IPGR1), .r_IPGR2(r_IPGR2), .r_MinFL(r_MinFL), + .r_MaxFL(r_MaxFL), .r_MaxRet(r_MaxRet), .r_CollValid(r_CollValid), + .r_TxFlow(r_TxFlow), .r_RxFlow(r_RxFlow), .r_PassAll(r_PassAll), + .r_MiiNoPre(r_MiiNoPre), .r_ClkDiv(r_ClkDiv), + .r_WCtrlData(r_WCtrlData), .r_RStat(r_RStat), .r_ScanStat(r_ScanStat), + .r_RGAD(r_RGAD), .r_FIAD(r_FIAD), .r_CtrlData(r_CtrlData), + .NValid_stat(NValid_stat), .Busy_stat(Busy_stat), + .LinkFail(LinkFail), .r_MAC(r_MAC), .WCtrlDataStart(WCtrlDataStart), + .RStatStart(RStatStart), .UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg), .Prsd(Prsd), + .r_TxBDNum(r_TxBDNum), .int_o(int_o), + .r_HASH0(r_HASH0), .r_HASH1(r_HASH1), .r_TxPauseRq(r_TxPauseRq), + .r_TxPauseTV(r_TxPauseTV), .RstTxPauseRq(RstTxPauseRq), .TxCtrlEndFrm(TxCtrlEndFrm), + .StartTxDone(StartTxDone), .TxClk(mtx_clk_pad_i), .RxClk(mrx_clk_pad_i), + .SetPauseTimer(SetPauseTimer) + +); + + + +wire [7:0] RxData; +wire RxValid; +wire RxStartFrm; +wire RxEndFrm; +wire RxAbort; + +wire WillTransmit; // Will transmit (to RxEthMAC) +wire ResetCollision; // Reset Collision (for synchronizing collision) +wire [7:0] TxDataOut; // Transmit Packet Data (to TxEthMAC) +wire WillSendControlFrame; +wire ReceiveEnd; +wire ReceivedPacketGood; +wire ReceivedLengthOK; +wire InvalidSymbol; +wire LatchedCrcError; +wire RxLateCollision; +wire [3:0] RetryCntLatched; +wire [3:0] RetryCnt; +wire StartTxAbort; +wire MaxCollisionOccured; +wire RetryLimit; +wire StatePreamble; +wire [1:0] StateData; + +// Connecting MACControl +eth_maccontrol maccontrol1 +( + .MTxClk(mtx_clk_pad_i), .TPauseRq(TPauseRq), + .TxPauseTV(r_TxPauseTV), .TxDataIn(TxData), + .TxStartFrmIn(TxStartFrm), .TxEndFrmIn(TxEndFrm), + .TxUsedDataIn(TxUsedDataIn), .TxDoneIn(TxDoneIn), + .TxAbortIn(TxAbortIn), .MRxClk(mrx_clk_pad_i), + .RxData(RxData), .RxValid(RxValid), + .RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm), + .ReceiveEnd(ReceiveEnd), .ReceivedPacketGood(ReceivedPacketGood), + .TxFlow(r_TxFlow), + .RxFlow(r_RxFlow), .DlyCrcEn(r_DlyCrcEn), + .MAC(r_MAC), .PadIn(r_Pad | PerPacketPad), + .PadOut(PadOut), .CrcEnIn(r_CrcEn | PerPacketCrcEn), + .CrcEnOut(CrcEnOut), .TxReset(wb_rst_i), + .RxReset(wb_rst_i), .ReceivedLengthOK(ReceivedLengthOK), + .TxDataOut(TxDataOut), .TxStartFrmOut(TxStartFrmOut), + .TxEndFrmOut(TxEndFrmOut), .TxUsedDataOut(TxUsedData), + .TxDoneOut(TxDone), .TxAbortOut(TxAbort), + .WillSendControlFrame(WillSendControlFrame), .TxCtrlEndFrm(TxCtrlEndFrm), + .ReceivedPauseFrm(ReceivedPauseFrm), .ControlFrmAddressOK(ControlFrmAddressOK), + .SetPauseTimer(SetPauseTimer), + .RxStatusWriteLatched_sync2(RxStatusWriteLatched_sync2), .r_PassAll(r_PassAll) +); + + + +wire TxCarrierSense; // Synchronized CarrierSense (to Tx clock) +wire Collision; // Synchronized Collision + +reg CarrierSense_Tx1; +reg CarrierSense_Tx2; +reg Collision_Tx1; +reg Collision_Tx2; + +reg RxEnSync; // Synchronized Receive Enable +reg WillTransmit_q; +reg WillTransmit_q2; + + + +// Muxed MII receive data valid +assign MRxDV_Lb = r_LoopBck? mtxen_pad_o : mrxdv_pad_i & RxEnSync; + +// Muxed MII Receive Error +assign MRxErr_Lb = r_LoopBck? mtxerr_pad_o : mrxerr_pad_i & RxEnSync; + +// Muxed MII Receive Data +assign MRxD_Lb[3:0] = r_LoopBck? mtxd_pad_o[3:0] : mrxd_pad_i[3:0]; + + + +// Connecting TxEthMAC +eth_txethmac txethmac1 +( + .MTxClk(mtx_clk_pad_i), .Reset(wb_rst_i), .CarrierSense(TxCarrierSense), + .Collision(Collision), .TxData(TxDataOut), .TxStartFrm(TxStartFrmOut), + .TxUnderRun(TxUnderRun), .TxEndFrm(TxEndFrmOut), .Pad(PadOut), + .MinFL(r_MinFL), .CrcEn(CrcEnOut), .FullD(r_FullD), + .HugEn(r_HugEn), .DlyCrcEn(r_DlyCrcEn), .IPGT(r_IPGT), + .IPGR1(r_IPGR1), .IPGR2(r_IPGR2), .CollValid(r_CollValid), + .MaxRet(r_MaxRet), .NoBckof(r_NoBckof), .ExDfrEn(r_ExDfrEn), + .MaxFL(r_MaxFL), .MTxEn(mtxen_pad_o), .MTxD(mtxd_pad_o), + .MTxErr(mtxerr_pad_o), .TxUsedData(TxUsedDataIn), .TxDone(TxDoneIn), + .TxRetry(TxRetry), .TxAbort(TxAbortIn), .WillTransmit(WillTransmit), + .ResetCollision(ResetCollision), .RetryCnt(RetryCnt), .StartTxDone(StartTxDone), + .StartTxAbort(StartTxAbort), .MaxCollisionOccured(MaxCollisionOccured), .LateCollision(LateCollision), + .DeferIndication(DeferIndication), .StatePreamble(StatePreamble), .StateData(StateData) +); + + + + +wire [15:0] RxByteCnt; +wire RxByteCntEq0; +wire RxByteCntGreat2; +wire RxByteCntMaxFrame; +wire RxCrcError; +wire RxStateIdle; +wire RxStatePreamble; +wire RxStateSFD; +wire [1:0] RxStateData; +wire AddressMiss; + + + +// Connecting RxEthMAC +eth_rxethmac rxethmac1 +( + .MRxClk(mrx_clk_pad_i), .MRxDV(MRxDV_Lb), .MRxD(MRxD_Lb), + .Transmitting(Transmitting), .HugEn(r_HugEn), .DlyCrcEn(r_DlyCrcEn), + .MaxFL(r_MaxFL), .r_IFG(r_IFG), .Reset(wb_rst_i), + .RxData(RxData), .RxValid(RxValid), .RxStartFrm(RxStartFrm), + .RxEndFrm(RxEndFrm), .ByteCnt(RxByteCnt), + .ByteCntEq0(RxByteCntEq0), .ByteCntGreat2(RxByteCntGreat2), .ByteCntMaxFrame(RxByteCntMaxFrame), + .CrcError(RxCrcError), .StateIdle(RxStateIdle), .StatePreamble(RxStatePreamble), + .StateSFD(RxStateSFD), .StateData(RxStateData), + .MAC(r_MAC), .r_Pro(r_Pro), .r_Bro(r_Bro), + .r_HASH0(r_HASH0), .r_HASH1(r_HASH1), .RxAbort(RxAbort), + .AddressMiss(AddressMiss), .PassAll(r_PassAll), .ControlFrmAddressOK(ControlFrmAddressOK) +); + + +// MII Carrier Sense Synchronization +always @ (posedge mtx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + CarrierSense_Tx1 <= #Tp 1'b0; + CarrierSense_Tx2 <= #Tp 1'b0; + end + else + begin + CarrierSense_Tx1 <= #Tp mcrs_pad_i; + CarrierSense_Tx2 <= #Tp CarrierSense_Tx1; + end +end + +assign TxCarrierSense = ~r_FullD & CarrierSense_Tx2; + + +// MII Collision Synchronization +always @ (posedge mtx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + Collision_Tx1 <= #Tp 1'b0; + Collision_Tx2 <= #Tp 1'b0; + end + else + begin + Collision_Tx1 <= #Tp mcoll_pad_i; + if(ResetCollision) + Collision_Tx2 <= #Tp 1'b0; + else + if(Collision_Tx1) + Collision_Tx2 <= #Tp 1'b1; + end +end + + +// Synchronized Collision +assign Collision = ~r_FullD & Collision_Tx2; + + + +// Delayed WillTransmit +always @ (posedge mrx_clk_pad_i) +begin + WillTransmit_q <= #Tp WillTransmit; + WillTransmit_q2 <= #Tp WillTransmit_q; +end + + +assign Transmitting = ~r_FullD & WillTransmit_q2; + + + +// Synchronized Receive Enable +always @ (posedge mrx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + RxEnSync <= #Tp 1'b0; + else + if(~mrxdv_pad_i) + RxEnSync <= #Tp r_RxEn; +end + + + +// Synchronizing WillSendControlFrame to WB_CLK; +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + WillSendControlFrame_sync1 <= 1'b0; + else + WillSendControlFrame_sync1 <=#Tp WillSendControlFrame; +end + +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + WillSendControlFrame_sync2 <= 1'b0; + else + WillSendControlFrame_sync2 <=#Tp WillSendControlFrame_sync1; +end + +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + WillSendControlFrame_sync3 <= 1'b0; + else + WillSendControlFrame_sync3 <=#Tp WillSendControlFrame_sync2; +end + +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + RstTxPauseRq <= 1'b0; + else + RstTxPauseRq <=#Tp WillSendControlFrame_sync2 & ~WillSendControlFrame_sync3; +end + + + + +// TX Pause request Synchronization +always @ (posedge mtx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + TxPauseRq_sync1 <= #Tp 1'b0; + TxPauseRq_sync2 <= #Tp 1'b0; + TxPauseRq_sync3 <= #Tp 1'b0; + end + else + begin + TxPauseRq_sync1 <= #Tp (r_TxPauseRq & r_TxFlow); + TxPauseRq_sync2 <= #Tp TxPauseRq_sync1; + TxPauseRq_sync3 <= #Tp TxPauseRq_sync2; + end +end + + +always @ (posedge mtx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + TPauseRq <= #Tp 1'b0; + else + TPauseRq <= #Tp TxPauseRq_sync2 & (~TxPauseRq_sync3); +end + + +wire LatchedMRxErr; +reg RxAbort_latch; +reg RxAbort_sync1; +reg RxAbort_wb; +reg RxAbortRst_sync1; +reg RxAbortRst; + +// Synchronizing RxAbort to the WISHBONE clock +always @ (posedge mrx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + RxAbort_latch <= #Tp 1'b0; + else if(RxAbort | (ShortFrame & ~r_RecSmall) | LatchedMRxErr & ~InvalidSymbol | (ReceivedPauseFrm & (~r_PassAll))) + RxAbort_latch <= #Tp 1'b1; + else if(RxAbortRst) + RxAbort_latch <= #Tp 1'b0; +end + +always @ (posedge wb_clk_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + RxAbort_sync1 <= #Tp 1'b0; + RxAbort_wb <= #Tp 1'b0; + RxAbort_wb <= #Tp 1'b0; + end + else + begin + RxAbort_sync1 <= #Tp RxAbort_latch; + RxAbort_wb <= #Tp RxAbort_sync1; + end +end + +always @ (posedge mrx_clk_pad_i or posedge wb_rst_i) +begin + if(wb_rst_i) + begin + RxAbortRst_sync1 <= #Tp 1'b0; + RxAbortRst <= #Tp 1'b0; + end + else + begin + RxAbortRst_sync1 <= #Tp RxAbort_wb; + RxAbortRst <= #Tp RxAbortRst_sync1; + end +end + + + +// Connecting Wishbone module +eth_wishbone wishbone +( + .WB_CLK_I(wb_clk_i), .WB_DAT_I(wb_dat_i), + .WB_DAT_O(BD_WB_DAT_O), + + // WISHBONE slave + .WB_ADR_I(wb_adr_i[9:2]), .WB_WE_I(wb_we_i), + .BDCs(BDCs), .WB_ACK_O(BDAck), + + .Reset(wb_rst_i), + + // WISHBONE master + .m_wb_adr_o(m_wb_adr_tmp), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o), + .m_wb_dat_i(m_wb_dat_i), .m_wb_dat_o(m_wb_dat_o), .m_wb_cyc_o(m_wb_cyc_o), + .m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i), .m_wb_err_i(m_wb_err_i), + +`ifdef ETH_WISHBONE_B3 + .m_wb_cti_o(m_wb_cti_o), .m_wb_bte_o(m_wb_bte_o), +`endif + + + //TX + .MTxClk(mtx_clk_pad_i), .TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm), + .TxUsedData(TxUsedData), .TxData(TxData), + .TxRetry(TxRetry), .TxAbort(TxAbort), .TxUnderRun(TxUnderRun), + .TxDone(TxDone), + .PerPacketCrcEn(PerPacketCrcEn), .PerPacketPad(PerPacketPad), + + // Register + .r_TxEn(r_TxEn), .r_RxEn(r_RxEn), .r_TxBDNum(r_TxBDNum), + .r_RxFlow(r_RxFlow), .r_PassAll(r_PassAll), + + //RX + .MRxClk(mrx_clk_pad_i), .RxData(RxData), .RxValid(RxValid), + .RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm), + .Busy_IRQ(Busy_IRQ), .RxE_IRQ(RxE_IRQ), .RxB_IRQ(RxB_IRQ), + .TxE_IRQ(TxE_IRQ), .TxB_IRQ(TxB_IRQ), + + .RxAbort(RxAbort_wb), .RxStatusWriteLatched_sync2(RxStatusWriteLatched_sync2), + + .InvalidSymbol(InvalidSymbol), .LatchedCrcError(LatchedCrcError), .RxLength(RxByteCnt), + .RxLateCollision(RxLateCollision), .ShortFrame(ShortFrame), .DribbleNibble(DribbleNibble), + .ReceivedPacketTooBig(ReceivedPacketTooBig), .LoadRxStatus(LoadRxStatus), .RetryCntLatched(RetryCntLatched), + .RetryLimit(RetryLimit), .LateCollLatched(LateCollLatched), .DeferLatched(DeferLatched), + .RstDeferLatched(RstDeferLatched), + .CarrierSenseLost(CarrierSenseLost),.ReceivedPacketGood(ReceivedPacketGood), .AddressMiss(AddressMiss), + .ReceivedPauseFrm(ReceivedPauseFrm) + +`ifdef ETH_BIST + , + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +); + +assign m_wb_adr_o = {m_wb_adr_tmp, 2'h0}; + +// Connecting MacStatus module +eth_macstatus macstatus1 +( + .MRxClk(mrx_clk_pad_i), .Reset(wb_rst_i), + .ReceiveEnd(ReceiveEnd), .ReceivedPacketGood(ReceivedPacketGood), .ReceivedLengthOK(ReceivedLengthOK), + .RxCrcError(RxCrcError), .MRxErr(MRxErr_Lb), .MRxDV(MRxDV_Lb), + .RxStateSFD(RxStateSFD), .RxStateData(RxStateData), .RxStatePreamble(RxStatePreamble), + .RxStateIdle(RxStateIdle), .Transmitting(Transmitting), .RxByteCnt(RxByteCnt), + .RxByteCntEq0(RxByteCntEq0), .RxByteCntGreat2(RxByteCntGreat2), .RxByteCntMaxFrame(RxByteCntMaxFrame), + .InvalidSymbol(InvalidSymbol), + .MRxD(MRxD_Lb), .LatchedCrcError(LatchedCrcError), .Collision(mcoll_pad_i), + .CollValid(r_CollValid), .RxLateCollision(RxLateCollision), .r_RecSmall(r_RecSmall), + .r_MinFL(r_MinFL), .r_MaxFL(r_MaxFL), .ShortFrame(ShortFrame), + .DribbleNibble(DribbleNibble), .ReceivedPacketTooBig(ReceivedPacketTooBig), .r_HugEn(r_HugEn), + .LoadRxStatus(LoadRxStatus), .RetryCnt(RetryCnt), .StartTxDone(StartTxDone), + .StartTxAbort(StartTxAbort), .RetryCntLatched(RetryCntLatched), .MTxClk(mtx_clk_pad_i), + .MaxCollisionOccured(MaxCollisionOccured), .RetryLimit(RetryLimit), .LateCollision(LateCollision), + .LateCollLatched(LateCollLatched), .DeferIndication(DeferIndication), .DeferLatched(DeferLatched), + .RstDeferLatched(RstDeferLatched), + .TxStartFrm(TxStartFrmOut), .StatePreamble(StatePreamble), .StateData(StateData), + .CarrierSense(CarrierSense_Tx2), .CarrierSenseLost(CarrierSenseLost), .TxUsedData(TxUsedDataIn), + .LatchedMRxErr(LatchedMRxErr), .Loopback(r_LoopBck), .r_FullD(r_FullD) +); + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v new file mode 100644 index 000000000..34984182a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v @@ -0,0 +1,330 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_transmitcontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_transmitcontrol.v,v $ +// Revision 1.6 2002/11/21 00:16:14 mohor +// When TxUsedData and CtrlMux occur at the same time, byte counter needs +// to be incremented by 2. Signal IncrementByteCntBy2 added for that reason. +// +// Revision 1.5 2002/11/19 17:37:32 mohor +// When control frame (PAUSE) was sent, status was written in the +// eth_wishbone module and both TXB and TXC interrupts were set. Fixed. +// Only TXC interrupt is set. +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.1 2001/07/03 12:51:54 mohor +// Initial release of the MAC Control module. +// +// +// +// +// +// + + +`include "timescale.v" + + +module eth_transmitcontrol (MTxClk, TxReset, TxUsedDataIn, TxUsedDataOut, TxDoneIn, TxAbortIn, + TxStartFrmIn, TPauseRq, TxUsedDataOutDetected, TxFlow, DlyCrcEn, + TxPauseTV, MAC, TxCtrlStartFrm, TxCtrlEndFrm, SendingCtrlFrm, CtrlMux, + ControlData, WillSendControlFrame, BlockTxDone + ); + +parameter Tp = 1; + + +input MTxClk; +input TxReset; +input TxUsedDataIn; +input TxUsedDataOut; +input TxDoneIn; +input TxAbortIn; +input TxStartFrmIn; +input TPauseRq; +input TxUsedDataOutDetected; +input TxFlow; +input DlyCrcEn; +input [15:0] TxPauseTV; +input [47:0] MAC; + +output TxCtrlStartFrm; +output TxCtrlEndFrm; +output SendingCtrlFrm; +output CtrlMux; +output [7:0] ControlData; +output WillSendControlFrame; +output BlockTxDone; + +reg SendingCtrlFrm; +reg CtrlMux; +reg WillSendControlFrame; +reg [3:0] DlyCrcCnt; +reg [5:0] ByteCnt; +reg ControlEnd_q; +reg [7:0] MuxedCtrlData; +reg TxCtrlStartFrm; +reg TxCtrlStartFrm_q; +reg TxCtrlEndFrm; +reg [7:0] ControlData; +reg TxUsedDataIn_q; +reg BlockTxDone; + +wire IncrementDlyCrcCnt; +wire ResetByteCnt; +wire IncrementByteCnt; +wire ControlEnd; +wire IncrementByteCntBy2; +wire EnableCnt; + + +// A command for Sending the control frame is active (latched) +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + WillSendControlFrame <= #Tp 1'b0; + else + if(TxCtrlEndFrm & CtrlMux) + WillSendControlFrame <= #Tp 1'b0; + else + if(TPauseRq & TxFlow) + WillSendControlFrame <= #Tp 1'b1; +end + + +// Generation of the transmit control packet start frame +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + TxCtrlStartFrm <= #Tp 1'b0; + else + if(TxUsedDataIn_q & CtrlMux) + TxCtrlStartFrm <= #Tp 1'b0; + else + if(WillSendControlFrame & ~TxUsedDataOut & (TxDoneIn | TxAbortIn | TxStartFrmIn | (~TxUsedDataOutDetected))) + TxCtrlStartFrm <= #Tp 1'b1; +end + + + +// Generation of the transmit control packet end frame +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + TxCtrlEndFrm <= #Tp 1'b0; + else + if(ControlEnd | ControlEnd_q) + TxCtrlEndFrm <= #Tp 1'b1; + else + TxCtrlEndFrm <= #Tp 1'b0; +end + + +// Generation of the multiplexer signal (controls muxes for switching between +// normal and control packets) +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + CtrlMux <= #Tp 1'b0; + else + if(WillSendControlFrame & ~TxUsedDataOut) + CtrlMux <= #Tp 1'b1; + else + if(TxDoneIn) + CtrlMux <= #Tp 1'b0; +end + + + +// Generation of the Sending Control Frame signal (enables padding and CRC) +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + SendingCtrlFrm <= #Tp 1'b0; + else + if(WillSendControlFrame & TxCtrlStartFrm) + SendingCtrlFrm <= #Tp 1'b1; + else + if(TxDoneIn) + SendingCtrlFrm <= #Tp 1'b0; +end + + +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + TxUsedDataIn_q <= #Tp 1'b0; + else + TxUsedDataIn_q <= #Tp TxUsedDataIn; +end + + + +// Generation of the signal that will block sending the Done signal to the eth_wishbone module +// While sending the control frame +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + BlockTxDone <= #Tp 1'b0; + else + if(TxCtrlStartFrm) + BlockTxDone <= #Tp 1'b1; + else + if(TxStartFrmIn) + BlockTxDone <= #Tp 1'b0; +end + + +always @ (posedge MTxClk) +begin + ControlEnd_q <= #Tp ControlEnd; + TxCtrlStartFrm_q <= #Tp TxCtrlStartFrm; +end + + +assign IncrementDlyCrcCnt = CtrlMux & TxUsedDataIn & ~DlyCrcCnt[2]; + + +// Delayed CRC counter +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + DlyCrcCnt <= #Tp 4'h0; + else + if(ResetByteCnt) + DlyCrcCnt <= #Tp 4'h0; + else + if(IncrementDlyCrcCnt) + DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1; +end + + +assign ResetByteCnt = TxReset | (~TxCtrlStartFrm & (TxDoneIn | TxAbortIn)); +assign IncrementByteCnt = CtrlMux & (TxCtrlStartFrm & ~TxCtrlStartFrm_q & ~TxUsedDataIn | TxUsedDataIn & ~ControlEnd); +assign IncrementByteCntBy2 = CtrlMux & TxCtrlStartFrm & (~TxCtrlStartFrm_q) & TxUsedDataIn; // When TxUsedDataIn and CtrlMux are set at the same time + +assign EnableCnt = (~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0])); +// Byte counter +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + ByteCnt <= #Tp 6'h0; + else + if(ResetByteCnt) + ByteCnt <= #Tp 6'h0; + else + if(IncrementByteCntBy2 & EnableCnt) + ByteCnt <= #Tp (ByteCnt[5:0] ) + 2'h2; + else + if(IncrementByteCnt & EnableCnt) + ByteCnt <= #Tp (ByteCnt[5:0] ) + 1'b1; +end + + +assign ControlEnd = ByteCnt[5:0] == 6'h22; + + +// Control data generation (goes to the TxEthMAC module) +always @ (ByteCnt or DlyCrcEn or MAC or TxPauseTV or DlyCrcCnt) +begin + case(ByteCnt) + 6'h0: if(~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0])) + MuxedCtrlData[7:0] = 8'h01; // Reserved Multicast Address + else + MuxedCtrlData[7:0] = 8'h0; + 6'h2: MuxedCtrlData[7:0] = 8'h80; + 6'h4: MuxedCtrlData[7:0] = 8'hC2; + 6'h6: MuxedCtrlData[7:0] = 8'h00; + 6'h8: MuxedCtrlData[7:0] = 8'h00; + 6'hA: MuxedCtrlData[7:0] = 8'h01; + 6'hC: MuxedCtrlData[7:0] = MAC[47:40]; + 6'hE: MuxedCtrlData[7:0] = MAC[39:32]; + 6'h10: MuxedCtrlData[7:0] = MAC[31:24]; + 6'h12: MuxedCtrlData[7:0] = MAC[23:16]; + 6'h14: MuxedCtrlData[7:0] = MAC[15:8]; + 6'h16: MuxedCtrlData[7:0] = MAC[7:0]; + 6'h18: MuxedCtrlData[7:0] = 8'h88; // Type/Length + 6'h1A: MuxedCtrlData[7:0] = 8'h08; + 6'h1C: MuxedCtrlData[7:0] = 8'h00; // Opcode + 6'h1E: MuxedCtrlData[7:0] = 8'h01; + 6'h20: MuxedCtrlData[7:0] = TxPauseTV[15:8]; // Pause timer value + 6'h22: MuxedCtrlData[7:0] = TxPauseTV[7:0]; + default: MuxedCtrlData[7:0] = 8'h0; + endcase +end + + +// Latched Control data +always @ (posedge MTxClk or posedge TxReset) +begin + if(TxReset) + ControlData[7:0] <= #Tp 8'h0; + else + if(~ByteCnt[0]) + ControlData[7:0] <= #Tp MuxedCtrlData[7:0]; +end + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v new file mode 100644 index 000000000..ef2c20aa1 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v @@ -0,0 +1,224 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_txcounters.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_txcounters.v,v $ +// Revision 1.6 2005/02/21 11:25:27 igorm +// Delayed CRC fixed. +// +// Revision 1.5 2002/04/22 14:54:14 mohor +// FCS should not be included in NibbleMinFl. +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.4 2001/06/27 21:27:45 mohor +// Few typos fixed. +// +// Revision 1.2 2001/06/19 10:38:07 mohor +// Minor changes in header. +// +// Revision 1.1 2001/06/19 10:27:57 mohor +// TxEthMAC initial release. +// +// +// + + +`include "timescale.v" + + +module eth_txcounters (StatePreamble, StateIPG, StateData, StatePAD, StateFCS, StateJam, + StateBackOff, StateDefer, StateIdle, StartDefer, StartIPG, StartFCS, + StartJam, StartBackoff, TxStartFrm, MTxClk, Reset, MinFL, MaxFL, HugEn, + ExDfrEn, PacketFinished_q, DlyCrcEn, StateSFD, ByteCnt, NibCnt, + ExcessiveDefer, NibCntEq7, NibCntEq15, MaxFrame, NibbleMinFl, DlyCrcCnt + ); + +parameter Tp = 1; + +input MTxClk; // Tx clock +input Reset; // Reset +input StatePreamble; // Preamble state +input StateIPG; // IPG state +input [1:0] StateData; // Data state +input StatePAD; // PAD state +input StateFCS; // FCS state +input StateJam; // Jam state +input StateBackOff; // Backoff state +input StateDefer; // Defer state +input StateIdle; // Idle state +input StateSFD; // SFD state +input StartDefer; // Defer state will be activated in next clock +input StartIPG; // IPG state will be activated in next clock +input StartFCS; // FCS state will be activated in next clock +input StartJam; // Jam state will be activated in next clock +input StartBackoff; // Backoff state will be activated in next clock +input TxStartFrm; // Tx start frame +input [15:0] MinFL; // Minimum frame length (in bytes) +input [15:0] MaxFL; // Miximum frame length (in bytes) +input HugEn; // Pakets bigger then MaxFL enabled +input ExDfrEn; // Excessive deferral enabled +input PacketFinished_q; +input DlyCrcEn; // Delayed CRC enabled + +output [15:0] ByteCnt; // Byte counter +output [15:0] NibCnt; // Nibble counter +output ExcessiveDefer; // Excessive Deferral occuring +output NibCntEq7; // Nibble counter is equal to 7 +output NibCntEq15; // Nibble counter is equal to 15 +output MaxFrame; // Maximum frame occured +output NibbleMinFl; // Nibble counter is greater than the minimum frame length +output [2:0] DlyCrcCnt; // Delayed CRC Count + +wire ExcessiveDeferCnt; +wire ResetNibCnt; +wire IncrementNibCnt; +wire ResetByteCnt; +wire IncrementByteCnt; +wire ByteCntMax; + +reg [15:0] NibCnt; +reg [15:0] ByteCnt; +reg [2:0] DlyCrcCnt; + + + +assign IncrementNibCnt = StateIPG | StatePreamble | (|StateData) | StatePAD + | StateFCS | StateJam | StateBackOff | StateDefer & ~ExcessiveDefer & TxStartFrm; + + +assign ResetNibCnt = StateDefer & ExcessiveDefer & ~TxStartFrm | StatePreamble & NibCntEq15 + | StateJam & NibCntEq7 | StateIdle | StartDefer | StartIPG | StartFCS | StartJam; + +// Nibble Counter +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + NibCnt <= #Tp 16'h0; + else + begin + if(ResetNibCnt) + NibCnt <= #Tp 16'h0; + else + if(IncrementNibCnt) + NibCnt <= #Tp NibCnt + 1'b1; + end +end + + +assign NibCntEq7 = &NibCnt[2:0]; +assign NibCntEq15 = &NibCnt[3:0]; + +assign NibbleMinFl = NibCnt >= (((MinFL-3'h4)<<1) -1); // FCS should not be included in NibbleMinFl + +assign ExcessiveDeferCnt = NibCnt[13:0] == 16'h17b7; + +assign ExcessiveDefer = NibCnt[13:0] == 16'h17b7 & ~ExDfrEn; // 6071 nibbles + +assign IncrementByteCnt = StateData[1] & ~ByteCntMax + | StateBackOff & (&NibCnt[6:0]) + | (StatePAD | StateFCS) & NibCnt[0] & ~ByteCntMax; + +assign ResetByteCnt = StartBackoff | StateIdle & TxStartFrm | PacketFinished_q; + + +// Transmit Byte Counter +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ByteCnt[15:0] <= #Tp 16'h0; + else + begin + if(ResetByteCnt) + ByteCnt[15:0] <= #Tp 16'h0; + else + if(IncrementByteCnt) + ByteCnt[15:0] <= #Tp ByteCnt[15:0] + 1'b1; + end +end + + +assign MaxFrame = ByteCnt[15:0] == MaxFL[15:0] & ~HugEn; + +assign ByteCntMax = &ByteCnt[15:0]; + + +// Delayed CRC counter +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + DlyCrcCnt <= #Tp 3'h0; + else + begin + if(StateData[1] & DlyCrcCnt == 3'h4 | StartJam | PacketFinished_q) + DlyCrcCnt <= #Tp 3'h0; + else + if(DlyCrcEn & (StateSFD | StateData[1] & (|DlyCrcCnt[2:0]))) + DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1; + end +end + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v new file mode 100644 index 000000000..eaa903741 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v @@ -0,0 +1,495 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_txethmac.v //// +/// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_txethmac.v,v $ +// Revision 1.9 2005/02/21 11:25:28 igorm +// Delayed CRC fixed. +// +// Revision 1.8 2003/01/30 13:33:24 mohor +// When padding was enabled and crc disabled, frame was not ended correctly. +// +// Revision 1.7 2002/02/26 16:24:01 mohor +// RetryCntLatched was unused and removed from design +// +// Revision 1.6 2002/02/22 12:56:35 mohor +// Retry is not activated when a Tx Underrun occured +// +// Revision 1.5 2002/02/11 09:18:22 mohor +// Tx status is written back to the BD. +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/19 18:16:40 mohor +// TxClk changed to MTxClk (as discribed in the documentation). +// Crc changed so only one file can be used instead of two. +// +// Revision 1.2 2001/06/19 10:38:08 mohor +// Minor changes in header. +// +// Revision 1.1 2001/06/19 10:27:58 mohor +// TxEthMAC initial release. +// +// +// + +`include "timescale.v" + + +module eth_txethmac (MTxClk, Reset, TxStartFrm, TxEndFrm, TxUnderRun, TxData, CarrierSense, + Collision, Pad, CrcEn, FullD, HugEn, DlyCrcEn, MinFL, MaxFL, IPGT, + IPGR1, IPGR2, CollValid, MaxRet, NoBckof, ExDfrEn, + MTxD, MTxEn, MTxErr, TxDone, TxRetry, TxAbort, TxUsedData, WillTransmit, + ResetCollision, RetryCnt, StartTxDone, StartTxAbort, MaxCollisionOccured, + LateCollision, DeferIndication, StatePreamble, StateData + + ); + +parameter Tp = 1; + + +input MTxClk; // Transmit clock (from PHY) +input Reset; // Reset +input TxStartFrm; // Transmit packet start frame +input TxEndFrm; // Transmit packet end frame +input TxUnderRun; // Transmit packet under-run +input [7:0] TxData; // Transmit packet data byte +input CarrierSense; // Carrier sense (synchronized) +input Collision; // Collision (synchronized) +input Pad; // Pad enable (from register) +input CrcEn; // Crc enable (from register) +input FullD; // Full duplex (from register) +input HugEn; // Huge packets enable (from register) +input DlyCrcEn; // Delayed Crc enabled (from register) +input [15:0] MinFL; // Minimum frame length (from register) +input [15:0] MaxFL; // Maximum frame length (from register) +input [6:0] IPGT; // Back to back transmit inter packet gap parameter (from register) +input [6:0] IPGR1; // Non back to back transmit inter packet gap parameter IPGR1 (from register) +input [6:0] IPGR2; // Non back to back transmit inter packet gap parameter IPGR2 (from register) +input [5:0] CollValid; // Valid collision window (from register) +input [3:0] MaxRet; // Maximum retry number (from register) +input NoBckof; // No backoff (from register) +input ExDfrEn; // Excessive defferal enable (from register) + +output [3:0] MTxD; // Transmit nibble (to PHY) +output MTxEn; // Transmit enable (to PHY) +output MTxErr; // Transmit error (to PHY) +output TxDone; // Transmit packet done (to RISC) +output TxRetry; // Transmit packet retry (to RISC) +output TxAbort; // Transmit packet abort (to RISC) +output TxUsedData; // Transmit packet used data (to RISC) +output WillTransmit; // Will transmit (to RxEthMAC) +output ResetCollision; // Reset Collision (for synchronizing collision) +output [3:0] RetryCnt; // Latched Retry Counter for tx status purposes +output StartTxDone; +output StartTxAbort; +output MaxCollisionOccured; +output LateCollision; +output DeferIndication; +output StatePreamble; +output [1:0] StateData; + +reg [3:0] MTxD; +reg MTxEn; +reg MTxErr; +reg TxDone; +reg TxRetry; +reg TxAbort; +reg TxUsedData; +reg WillTransmit; +reg ColWindow; +reg StopExcessiveDeferOccured; +reg [3:0] RetryCnt; +reg [3:0] MTxD_d; +reg StatusLatch; +reg PacketFinished_q; +reg PacketFinished; + + +wire ExcessiveDeferOccured; +wire StartIPG; +wire StartPreamble; +wire [1:0] StartData; +wire StartFCS; +wire StartJam; +wire StartDefer; +wire StartBackoff; +wire StateDefer; +wire StateIPG; +wire StateIdle; +wire StatePAD; +wire StateFCS; +wire StateJam; +wire StateJam_q; +wire StateBackOff; +wire StateSFD; +wire StartTxRetry; +wire UnderRun; +wire TooBig; +wire [31:0] Crc; +wire CrcError; +wire [2:0] DlyCrcCnt; +wire [15:0] NibCnt; +wire NibCntEq7; +wire NibCntEq15; +wire NibbleMinFl; +wire ExcessiveDefer; +wire [15:0] ByteCnt; +wire MaxFrame; +wire RetryMax; +wire RandomEq0; +wire RandomEqByteCnt; +wire PacketFinished_d; + + + +assign ResetCollision = ~(StatePreamble | (|StateData) | StatePAD | StateFCS); + +assign ExcessiveDeferOccured = TxStartFrm & StateDefer & ExcessiveDefer & ~StopExcessiveDeferOccured; + +assign StartTxDone = ~Collision & (StateFCS & NibCntEq7 | StateData[1] & TxEndFrm & (~Pad | Pad & NibbleMinFl) & ~CrcEn); + +assign UnderRun = StateData[0] & TxUnderRun & ~Collision; + +assign TooBig = ~Collision & MaxFrame & (StateData[0] & ~TxUnderRun | StateFCS); + +// assign StartTxRetry = StartJam & (ColWindow & ~RetryMax); +assign StartTxRetry = StartJam & (ColWindow & ~RetryMax) & ~UnderRun; + +assign LateCollision = StartJam & ~ColWindow & ~UnderRun; + +assign MaxCollisionOccured = StartJam & ColWindow & RetryMax; + +assign StateSFD = StatePreamble & NibCntEq15; + +assign StartTxAbort = TooBig | UnderRun | ExcessiveDeferOccured | LateCollision | MaxCollisionOccured; + + +// StopExcessiveDeferOccured +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + StopExcessiveDeferOccured <= #Tp 1'b0; + else + begin + if(~TxStartFrm) + StopExcessiveDeferOccured <= #Tp 1'b0; + else + if(ExcessiveDeferOccured) + StopExcessiveDeferOccured <= #Tp 1'b1; + end +end + + +// Collision Window +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ColWindow <= #Tp 1'b1; + else + begin + if(~Collision & ByteCnt[5:0] == CollValid[5:0] & (StateData[1] | StatePAD & NibCnt[0] | StateFCS & NibCnt[0])) + ColWindow <= #Tp 1'b0; + else + if(StateIdle | StateIPG) + ColWindow <= #Tp 1'b1; + end +end + + +// Start Window +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + StatusLatch <= #Tp 1'b0; + else + begin + if(~TxStartFrm) + StatusLatch <= #Tp 1'b0; + else + if(ExcessiveDeferOccured | StateIdle) + StatusLatch <= #Tp 1'b1; + end +end + + +// Transmit packet used data +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxUsedData <= #Tp 1'b0; + else + TxUsedData <= #Tp |StartData; +end + + +// Transmit packet done +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxDone <= #Tp 1'b0; + else + begin + if(TxStartFrm & ~StatusLatch) + TxDone <= #Tp 1'b0; + else + if(StartTxDone) + TxDone <= #Tp 1'b1; + end +end + + +// Transmit packet retry +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxRetry <= #Tp 1'b0; + else + begin + if(TxStartFrm & ~StatusLatch) + TxRetry <= #Tp 1'b0; + else + if(StartTxRetry) + TxRetry <= #Tp 1'b1; + end +end + + +// Transmit packet abort +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxAbort <= #Tp 1'b0; + else + begin + if(TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured) + TxAbort <= #Tp 1'b0; + else + if(StartTxAbort) + TxAbort <= #Tp 1'b1; + end +end + + +// Retry counter +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + RetryCnt[3:0] <= #Tp 4'h0; + else + begin + if(ExcessiveDeferOccured | UnderRun | TooBig | StartTxDone | TxUnderRun + | StateJam & NibCntEq7 & (~ColWindow | RetryMax)) + RetryCnt[3:0] <= #Tp 4'h0; + else + if(StateJam & NibCntEq7 & ColWindow & (RandomEq0 | NoBckof) | StateBackOff & RandomEqByteCnt) + RetryCnt[3:0] <= #Tp RetryCnt[3:0] + 1'b1; + end +end + + +assign RetryMax = RetryCnt[3:0] == MaxRet[3:0]; + + +// Transmit nibble +always @ (StatePreamble or StateData or StateData or StateFCS or StateJam or StateSFD or TxData or + Crc or NibCntEq15) +begin + if(StateData[0]) + MTxD_d[3:0] = TxData[3:0]; // Lower nibble + else + if(StateData[1]) + MTxD_d[3:0] = TxData[7:4]; // Higher nibble + else + if(StateFCS) + MTxD_d[3:0] = {~Crc[28], ~Crc[29], ~Crc[30], ~Crc[31]}; // Crc + else + if(StateJam) + MTxD_d[3:0] = 4'h9; // Jam pattern + else + if(StatePreamble) + if(NibCntEq15) + MTxD_d[3:0] = 4'hd; // SFD + else + MTxD_d[3:0] = 4'h5; // Preamble + else + MTxD_d[3:0] = 4'h0; +end + + +// Transmit Enable +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + MTxEn <= #Tp 1'b0; + else + MTxEn <= #Tp StatePreamble | (|StateData) | StatePAD | StateFCS | StateJam; +end + + +// Transmit nibble +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + MTxD[3:0] <= #Tp 4'h0; + else + MTxD[3:0] <= #Tp MTxD_d[3:0]; +end + + +// Transmit error +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + MTxErr <= #Tp 1'b0; + else + MTxErr <= #Tp TooBig | UnderRun; +end + + +// WillTransmit +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + WillTransmit <= #Tp 1'b0; + else + WillTransmit <= #Tp StartPreamble | StatePreamble | (|StateData) | StatePAD | StateFCS | StateJam; +end + + +assign PacketFinished_d = StartTxDone | TooBig | UnderRun | LateCollision | MaxCollisionOccured | ExcessiveDeferOccured; + + +// Packet finished +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + begin + PacketFinished <= #Tp 1'b0; + PacketFinished_q <= #Tp 1'b0; + end + else + begin + PacketFinished <= #Tp PacketFinished_d; + PacketFinished_q <= #Tp PacketFinished; + end +end + + +// Connecting module Counters +eth_txcounters txcounters1 (.StatePreamble(StatePreamble), .StateIPG(StateIPG), .StateData(StateData), + .StatePAD(StatePAD), .StateFCS(StateFCS), .StateJam(StateJam), .StateBackOff(StateBackOff), + .StateDefer(StateDefer), .StateIdle(StateIdle), .StartDefer(StartDefer), .StartIPG(StartIPG), + .StartFCS(StartFCS), .StartJam(StartJam), .TxStartFrm(TxStartFrm), .MTxClk(MTxClk), + .Reset(Reset), .MinFL(MinFL), .MaxFL(MaxFL), .HugEn(HugEn), .ExDfrEn(ExDfrEn), + .PacketFinished_q(PacketFinished_q), .DlyCrcEn(DlyCrcEn), .StartBackoff(StartBackoff), + .StateSFD(StateSFD), .ByteCnt(ByteCnt), .NibCnt(NibCnt), .ExcessiveDefer(ExcessiveDefer), + .NibCntEq7(NibCntEq7), .NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .NibbleMinFl(NibbleMinFl), + .DlyCrcCnt(DlyCrcCnt) + ); + + +// Connecting module StateM +eth_txstatem txstatem1 (.MTxClk(MTxClk), .Reset(Reset), .ExcessiveDefer(ExcessiveDefer), .CarrierSense(CarrierSense), + .NibCnt(NibCnt[6:0]), .IPGT(IPGT), .IPGR1(IPGR1), .IPGR2(IPGR2), .FullD(FullD), + .TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm), .TxUnderRun(TxUnderRun), .Collision(Collision), + .UnderRun(UnderRun), .StartTxDone(StartTxDone), .TooBig(TooBig), .NibCntEq7(NibCntEq7), + .NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .Pad(Pad), .CrcEn(CrcEn), + .NibbleMinFl(NibbleMinFl), .RandomEq0(RandomEq0), .ColWindow(ColWindow), .RetryMax(RetryMax), + .NoBckof(NoBckof), .RandomEqByteCnt(RandomEqByteCnt), .StateIdle(StateIdle), + .StateIPG(StateIPG), .StatePreamble(StatePreamble), .StateData(StateData), .StatePAD(StatePAD), + .StateFCS(StateFCS), .StateJam(StateJam), .StateJam_q(StateJam_q), .StateBackOff(StateBackOff), + .StateDefer(StateDefer), .StartFCS(StartFCS), .StartJam(StartJam), .StartBackoff(StartBackoff), + .StartDefer(StartDefer), .DeferIndication(DeferIndication), .StartPreamble(StartPreamble), .StartData(StartData), .StartIPG(StartIPG) + ); + + +wire Enable_Crc; +wire [3:0] Data_Crc; +wire Initialize_Crc; + +assign Enable_Crc = ~StateFCS; + +assign Data_Crc[0] = StateData[0]? TxData[3] : StateData[1]? TxData[7] : 1'b0; +assign Data_Crc[1] = StateData[0]? TxData[2] : StateData[1]? TxData[6] : 1'b0; +assign Data_Crc[2] = StateData[0]? TxData[1] : StateData[1]? TxData[5] : 1'b0; +assign Data_Crc[3] = StateData[0]? TxData[0] : StateData[1]? TxData[4] : 1'b0; + +assign Initialize_Crc = StateIdle | StatePreamble | (|DlyCrcCnt); + + +// Connecting module Crc +eth_crc txcrc (.Clk(MTxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc), + .Crc(Crc), .CrcError(CrcError) + ); + + +// Connecting module Random +eth_random random1 (.MTxClk(MTxClk), .Reset(Reset), .StateJam(StateJam), .StateJam_q(StateJam_q), .RetryCnt(RetryCnt), + .NibCnt(NibCnt), .ByteCnt(ByteCnt[9:0]), .RandomEq0(RandomEq0), .RandomEqByteCnt(RandomEqByteCnt)); + + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v new file mode 100644 index 000000000..17136a99e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v @@ -0,0 +1,287 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_txstatem.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// - Novan Hartadi (novan@vlsi.itb.ac.id) //// +//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_txstatem.v,v $ +// Revision 1.6 2003/01/30 13:29:08 tadejm +// Defer indication changed. +// +// Revision 1.5 2002/10/30 12:54:50 mohor +// State machine goes from idle to the defer state when CarrierSense is 1. FCS (CRC appending) fixed to check the CrcEn bit also when padding is necessery. +// +// Revision 1.4 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.3 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.2 2001/09/11 14:17:00 mohor +// Few little NCSIM warnings fixed. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/19 18:16:40 mohor +// TxClk changed to MTxClk (as discribed in the documentation). +// Crc changed so only one file can be used instead of two. +// +// Revision 1.2 2001/06/19 10:38:07 mohor +// Minor changes in header. +// +// Revision 1.1 2001/06/19 10:27:57 mohor +// TxEthMAC initial release. +// +// +// +// + + +`include "timescale.v" + + +module eth_txstatem (MTxClk, Reset, ExcessiveDefer, CarrierSense, NibCnt, IPGT, IPGR1, + IPGR2, FullD, TxStartFrm, TxEndFrm, TxUnderRun, Collision, UnderRun, + StartTxDone, TooBig, NibCntEq7, NibCntEq15, MaxFrame, Pad, CrcEn, + NibbleMinFl, RandomEq0, ColWindow, RetryMax, NoBckof, RandomEqByteCnt, + StateIdle, StateIPG, StatePreamble, StateData, StatePAD, StateFCS, + StateJam, StateJam_q, StateBackOff, StateDefer, StartFCS, StartJam, + StartBackoff, StartDefer, DeferIndication, StartPreamble, StartData, StartIPG + ); + +parameter Tp = 1; + +input MTxClk; +input Reset; +input ExcessiveDefer; +input CarrierSense; +input [6:0] NibCnt; +input [6:0] IPGT; +input [6:0] IPGR1; +input [6:0] IPGR2; +input FullD; +input TxStartFrm; +input TxEndFrm; +input TxUnderRun; +input Collision; +input UnderRun; +input StartTxDone; +input TooBig; +input NibCntEq7; +input NibCntEq15; +input MaxFrame; +input Pad; +input CrcEn; +input NibbleMinFl; +input RandomEq0; +input ColWindow; +input RetryMax; +input NoBckof; +input RandomEqByteCnt; + + +output StateIdle; // Idle state +output StateIPG; // IPG state +output StatePreamble; // Preamble state +output [1:0] StateData; // Data state +output StatePAD; // PAD state +output StateFCS; // FCS state +output StateJam; // Jam state +output StateJam_q; // Delayed Jam state +output StateBackOff; // Backoff state +output StateDefer; // Defer state + +output StartFCS; // FCS state will be activated in next clock +output StartJam; // Jam state will be activated in next clock +output StartBackoff; // Backoff state will be activated in next clock +output StartDefer; // Defer state will be activated in next clock +output DeferIndication; +output StartPreamble; // Preamble state will be activated in next clock +output [1:0] StartData; // Data state will be activated in next clock +output StartIPG; // IPG state will be activated in next clock + +wire StartIdle; // Idle state will be activated in next clock +wire StartPAD; // PAD state will be activated in next clock + + +reg StateIdle; +reg StateIPG; +reg StatePreamble; +reg [1:0] StateData; +reg StatePAD; +reg StateFCS; +reg StateJam; +reg StateJam_q; +reg StateBackOff; +reg StateDefer; +reg Rule1; + + +// Defining the next state +assign StartIPG = StateDefer & ~ExcessiveDefer & ~CarrierSense; + +assign StartIdle = StateIPG & (Rule1 & NibCnt[6:0] >= IPGT | ~Rule1 & NibCnt[6:0] >= IPGR2); + +assign StartPreamble = StateIdle & TxStartFrm & ~CarrierSense; + +assign StartData[0] = ~Collision & (StatePreamble & NibCntEq15 | StateData[1] & ~TxEndFrm); + +assign StartData[1] = ~Collision & StateData[0] & ~TxUnderRun & ~MaxFrame; + +assign StartPAD = ~Collision & StateData[1] & TxEndFrm & Pad & ~NibbleMinFl; + +assign StartFCS = ~Collision & StateData[1] & TxEndFrm & (~Pad | Pad & NibbleMinFl) & CrcEn + | ~Collision & StatePAD & NibbleMinFl & CrcEn; + +assign StartJam = (Collision | UnderRun) & ((StatePreamble & NibCntEq15) | (|StateData[1:0]) | StatePAD | StateFCS); + +assign StartBackoff = StateJam & ~RandomEq0 & ColWindow & ~RetryMax & NibCntEq7 & ~NoBckof; + +assign StartDefer = StateIPG & ~Rule1 & CarrierSense & NibCnt[6:0] <= IPGR1 & NibCnt[6:0] != IPGR2 + | StateIdle & CarrierSense + | StateJam & NibCntEq7 & (NoBckof | RandomEq0 | ~ColWindow | RetryMax) + | StateBackOff & (TxUnderRun | RandomEqByteCnt) + | StartTxDone | TooBig; + +assign DeferIndication = StateIdle & CarrierSense; + +// Tx State Machine +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + begin + StateIPG <= #Tp 1'b0; + StateIdle <= #Tp 1'b0; + StatePreamble <= #Tp 1'b0; + StateData[1:0] <= #Tp 2'b0; + StatePAD <= #Tp 1'b0; + StateFCS <= #Tp 1'b0; + StateJam <= #Tp 1'b0; + StateJam_q <= #Tp 1'b0; + StateBackOff <= #Tp 1'b0; + StateDefer <= #Tp 1'b1; + end + else + begin + StateData[1:0] <= #Tp StartData[1:0]; + StateJam_q <= #Tp StateJam; + + if(StartDefer | StartIdle) + StateIPG <= #Tp 1'b0; + else + if(StartIPG) + StateIPG <= #Tp 1'b1; + + if(StartDefer | StartPreamble) + StateIdle <= #Tp 1'b0; + else + if(StartIdle) + StateIdle <= #Tp 1'b1; + + if(StartData[0] | StartJam) + StatePreamble <= #Tp 1'b0; + else + if(StartPreamble) + StatePreamble <= #Tp 1'b1; + + if(StartFCS | StartJam) + StatePAD <= #Tp 1'b0; + else + if(StartPAD) + StatePAD <= #Tp 1'b1; + + if(StartJam | StartDefer) + StateFCS <= #Tp 1'b0; + else + if(StartFCS) + StateFCS <= #Tp 1'b1; + + if(StartBackoff | StartDefer) + StateJam <= #Tp 1'b0; + else + if(StartJam) + StateJam <= #Tp 1'b1; + + if(StartDefer) + StateBackOff <= #Tp 1'b0; + else + if(StartBackoff) + StateBackOff <= #Tp 1'b1; + + if(StartIPG) + StateDefer <= #Tp 1'b0; + else + if(StartDefer) + StateDefer <= #Tp 1'b1; + end +end + + +// This sections defines which interpack gap rule to use +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + Rule1 <= #Tp 1'b0; + else + begin + if(StateIdle | StateBackOff) + Rule1 <= #Tp 1'b0; + else + if(StatePreamble | FullD) + Rule1 <= #Tp 1'b1; + end +end + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v new file mode 100644 index 000000000..d1a98ace5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v @@ -0,0 +1,2559 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_wishbone.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_wishbone.v,v $ +// Revision 1.58 2005/03/21 20:07:18 igorm +// Some small fixes + some troubles fixed. +// +// Revision 1.57 2005/02/21 11:35:33 igorm +// Defer indication fixed. +// +// Revision 1.56 2004/04/30 10:30:00 igorm +// Accidently deleted line put back. +// +// Revision 1.55 2004/04/26 15:26:23 igorm +// - Bug connected to the TX_BD_NUM_Wr signal fixed (bug came in with the +// previous update of the core. +// - TxBDAddress is set to 0 after the TX is enabled in the MODER register. +// - RxBDAddress is set to r_TxBDNum<<1 after the RX is enabled in the MODER +// register. (thanks to Mathias and Torbjorn) +// - Multicast reception was fixed. Thanks to Ulrich Gries +// +// Revision 1.54 2003/11/12 18:24:59 tadejm +// WISHBONE slave changed and tested from only 32-bit accesss to byte access. +// +// Revision 1.53 2003/10/17 07:46:17 markom +// mbist signals updated according to newest convention +// +// Revision 1.52 2003/01/30 14:51:31 mohor +// Reset has priority in some flipflops. +// +// Revision 1.51 2003/01/30 13:36:22 mohor +// A new bug (entered with previous update) fixed. When abort occured sometimes +// data transmission was blocked. +// +// Revision 1.50 2003/01/22 13:49:26 tadejm +// When control packets were received, they were ignored in some cases. +// +// Revision 1.49 2003/01/21 12:09:40 mohor +// When receiving normal data frame and RxFlow control was switched on, RXB +// interrupt was not set. +// +// Revision 1.48 2003/01/20 12:05:26 mohor +// When in full duplex, transmit was sometimes blocked. Fixed. +// +// Revision 1.47 2002/11/22 13:26:21 mohor +// Registers RxStatusWrite_rck and RxStatusWriteLatched were not used +// anywhere. Removed. +// +// Revision 1.46 2002/11/22 01:57:06 mohor +// Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort +// synchronized. +// +// Revision 1.45 2002/11/19 17:33:34 mohor +// AddressMiss status is connecting to the Rx BD. AddressMiss is identifying +// that a frame was received because of the promiscous mode. +// +// Revision 1.44 2002/11/13 22:21:40 tadejm +// RxError is not generated when small frame reception is enabled and small +// frames are received. +// +// Revision 1.43 2002/10/18 20:53:34 mohor +// case changed to casex. +// +// Revision 1.42 2002/10/18 17:04:20 tadejm +// Changed BIST scan signals. +// +// Revision 1.41 2002/10/18 15:42:09 tadejm +// Igor added WB burst support and repaired BUG when handling TX under-run and retry. +// +// Revision 1.40 2002/10/14 16:07:02 mohor +// TxStatus is written after last access to the TX fifo is finished (in case of abort +// or retry). TxDone is fixed. +// +// Revision 1.39 2002/10/11 15:35:20 mohor +// txfifo_cnt and rxfifo_cnt counters width is defined in the eth_define.v file, +// TxDone and TxRetry are generated after the current WISHBONE access is +// finished. +// +// Revision 1.38 2002/10/10 16:29:30 mohor +// BIST added. +// +// Revision 1.37 2002/09/11 14:18:46 mohor +// Sometimes both RxB_IRQ and RxE_IRQ were activated. Bug fixed. +// +// Revision 1.36 2002/09/10 13:48:46 mohor +// Reception is possible after RxPointer is read and not after BD is read. For +// that reason RxBDReady is changed to RxReady. +// Busy_IRQ interrupt connected. When there is no RxBD ready and frame +// comes, interrupt is generated. +// +// Revision 1.35 2002/09/10 10:35:23 mohor +// Ethernet debug registers removed. +// +// Revision 1.34 2002/09/08 16:31:49 mohor +// Async reset for WB_ACK_O removed (when core was in reset, it was +// impossible to access BDs). +// RxPointers and TxPointers names changed to be more descriptive. +// TxUnderRun synchronized. +// +// Revision 1.33 2002/09/04 18:47:57 mohor +// Debug registers reg1, 2, 3, 4 connected. Synchronization of many signals +// changed (bugs fixed). Access to un-alligned buffers fixed. RxAbort signal +// was not used OK. +// +// Revision 1.32 2002/08/14 19:31:48 mohor +// Register TX_BD_NUM is changed so it contains value of the Tx buffer descriptors. No +// need to multiply or devide any more. +// +// Revision 1.31 2002/07/25 18:29:01 mohor +// WriteRxDataToMemory signal changed so end of frame (when last word is +// written to fifo) is changed. +// +// Revision 1.30 2002/07/23 15:28:31 mohor +// Ram , used for BDs changed from generic_spram to eth_spram_256x32. +// +// Revision 1.29 2002/07/20 00:41:32 mohor +// ShiftEnded synchronization changed. +// +// Revision 1.28 2002/07/18 16:11:46 mohor +// RxBDAddress takes `ETH_TX_BD_NUM_DEF value after reset. +// +// Revision 1.27 2002/07/11 02:53:20 mohor +// RxPointer bug fixed. +// +// Revision 1.26 2002/07/10 13:12:38 mohor +// Previous bug wasn't succesfully removed. Now fixed. +// +// Revision 1.25 2002/07/09 23:53:24 mohor +// Master state machine had a bug when switching from master write to +// master read. +// +// Revision 1.24 2002/07/09 20:44:41 mohor +// m_wb_cyc_o signal released after every single transfer. +// +// Revision 1.23 2002/05/03 10:15:50 mohor +// Outputs registered. Reset changed for eth_wishbone module. +// +// Revision 1.22 2002/04/24 08:52:19 mohor +// Compiler directives added. Tx and Rx fifo size incremented. A "late collision" +// bug fixed. +// +// Revision 1.21 2002/03/29 16:18:11 lampret +// Small typo fixed. +// +// Revision 1.20 2002/03/25 16:19:12 mohor +// Any address can be used for Tx and Rx BD pointers. Address does not need +// to be aligned. +// +// Revision 1.19 2002/03/19 12:51:50 mohor +// Comments in Slovene language removed. +// +// Revision 1.18 2002/03/19 12:46:52 mohor +// casex changed with case, fifo reset changed. +// +// Revision 1.17 2002/03/09 16:08:45 mohor +// rx_fifo was not always cleared ok. Fixed. +// +// Revision 1.16 2002/03/09 13:51:20 mohor +// Status was not latched correctly sometimes. Fixed. +// +// Revision 1.15 2002/03/08 06:56:46 mohor +// Big Endian problem when sending frames fixed. +// +// Revision 1.14 2002/03/02 19:12:40 mohor +// Byte ordering changed (Big Endian used). casex changed with case because +// Xilinx Foundation had problems. Tested in HW. It WORKS. +// +// Revision 1.13 2002/02/26 16:59:55 mohor +// Small fixes for external/internal DMA missmatches. +// +// Revision 1.12 2002/02/26 16:22:07 mohor +// Interrupts changed +// +// Revision 1.11 2002/02/15 17:07:39 mohor +// Status was not written correctly when frames were discarted because of +// address mismatch. +// +// Revision 1.10 2002/02/15 12:17:39 mohor +// RxStartFrm cleared when abort or retry comes. +// +// Revision 1.9 2002/02/15 11:59:10 mohor +// Changes that were lost when updating from 1.5 to 1.8 fixed. +// +// Revision 1.8 2002/02/14 20:54:33 billditt +// Addition of new module eth_addrcheck.v +// +// Revision 1.7 2002/02/12 17:03:47 mohor +// RxOverRun added to statuses. +// +// Revision 1.6 2002/02/11 09:18:22 mohor +// Tx status is written back to the BD. +// +// Revision 1.5 2002/02/08 16:21:54 mohor +// Rx status is written back to the BD. +// +// Revision 1.4 2002/02/06 14:10:21 mohor +// non-DMA host interface added. Select the right configutation in eth_defines. +// +// Revision 1.3 2002/02/05 16:44:39 mohor +// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200 +// MHz. Statuses, overrun, control frame transmission and reception still need +// to be fixed. +// +// Revision 1.2 2002/02/01 12:46:51 mohor +// Tx part finished. TxStatus needs to be fixed. Pause request needs to be +// added. +// +// Revision 1.1 2002/01/23 10:47:59 mohor +// Initial version. Equals to eth_wishbonedma.v at this moment. +// +// +// + +`include "eth_defines.v" +`include "timescale.v" + + +module eth_wishbone + ( + + // WISHBONE common + WB_CLK_I, WB_DAT_I, WB_DAT_O, + + // WISHBONE slave + WB_ADR_I, WB_WE_I, WB_ACK_O, + BDCs, + + Reset, + + // WISHBONE master + m_wb_adr_o, m_wb_sel_o, m_wb_we_o, + m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o, + m_wb_stb_o, m_wb_ack_i, m_wb_err_i, + +`ifdef ETH_WISHBONE_B3 + m_wb_cti_o, m_wb_bte_o, +`endif + + //TX + MTxClk, TxStartFrm, TxEndFrm, TxUsedData, TxData, + TxRetry, TxAbort, TxUnderRun, TxDone, PerPacketCrcEn, + PerPacketPad, + + //RX + MRxClk, RxData, RxValid, RxStartFrm, RxEndFrm, RxAbort, RxStatusWriteLatched_sync2, + + // Register + r_TxEn, r_RxEn, r_TxBDNum, r_RxFlow, r_PassAll, + + // Interrupts + TxB_IRQ, TxE_IRQ, RxB_IRQ, RxE_IRQ, Busy_IRQ, + + // Rx Status + InvalidSymbol, LatchedCrcError, RxLateCollision, ShortFrame, DribbleNibble, + ReceivedPacketTooBig, RxLength, LoadRxStatus, ReceivedPacketGood, AddressMiss, + ReceivedPauseFrm, + + // Tx Status + RetryCntLatched, RetryLimit, LateCollLatched, DeferLatched, RstDeferLatched, CarrierSenseLost + + // Bist +`ifdef ETH_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif + + + + ); + + +parameter Tp = 1; + + +// WISHBONE common +input WB_CLK_I; // WISHBONE clock +input [31:0] WB_DAT_I; // WISHBONE data input +output [31:0] WB_DAT_O; // WISHBONE data output + +// WISHBONE slave +input [9:2] WB_ADR_I; // WISHBONE address input +input WB_WE_I; // WISHBONE write enable input +input [3:0] BDCs; // Buffer descriptors are selected +output WB_ACK_O; // WISHBONE acknowledge output + +// WISHBONE master +output [29:0] m_wb_adr_o; // +output [3:0] m_wb_sel_o; // +output m_wb_we_o; // +output [31:0] m_wb_dat_o; // +output m_wb_cyc_o; // +output m_wb_stb_o; // +input [31:0] m_wb_dat_i; // +input m_wb_ack_i; // +input m_wb_err_i; // + +`ifdef ETH_WISHBONE_B3 +output [2:0] m_wb_cti_o; // Cycle Type Identifier +output [1:0] m_wb_bte_o; // Burst Type Extension +reg [2:0] m_wb_cti_o; // Cycle Type Identifier +`endif + +input Reset; // Reset signal + +// Rx Status signals +input InvalidSymbol; // Invalid symbol was received during reception in 100 Mbps mode +input LatchedCrcError; // CRC error +input RxLateCollision; // Late collision occured while receiving frame +input ShortFrame; // Frame shorter then the minimum size (r_MinFL) was received while small packets are enabled (r_RecSmall) +input DribbleNibble; // Extra nibble received +input ReceivedPacketTooBig;// Received packet is bigger than r_MaxFL +input [15:0] RxLength; // Length of the incoming frame +input LoadRxStatus; // Rx status was loaded +input ReceivedPacketGood;// Received packet's length and CRC are good +input AddressMiss; // When a packet is received AddressMiss status is written to the Rx BD +input r_RxFlow; +input r_PassAll; +input ReceivedPauseFrm; + +// Tx Status signals +input [3:0] RetryCntLatched; // Latched Retry Counter +input RetryLimit; // Retry limit reached (Retry Max value + 1 attempts were made) +input LateCollLatched; // Late collision occured +input DeferLatched; // Defer indication (Frame was defered before sucessfully sent) +output RstDeferLatched; +input CarrierSenseLost; // Carrier Sense was lost during the frame transmission + +// Tx +input MTxClk; // Transmit clock (from PHY) +input TxUsedData; // Transmit packet used data +input TxRetry; // Transmit packet retry +input TxAbort; // Transmit packet abort +input TxDone; // Transmission ended +output TxStartFrm; // Transmit packet start frame +output TxEndFrm; // Transmit packet end frame +output [7:0] TxData; // Transmit packet data byte +output TxUnderRun; // Transmit packet under-run +output PerPacketCrcEn; // Per packet crc enable +output PerPacketPad; // Per packet pading + +// Rx +input MRxClk; // Receive clock (from PHY) +input [7:0] RxData; // Received data byte (from PHY) +input RxValid; // +input RxStartFrm; // +input RxEndFrm; // +input RxAbort; // This signal is set when address doesn't match. +output RxStatusWriteLatched_sync2; + +//Register +input r_TxEn; // Transmit enable +input r_RxEn; // Receive enable +input [7:0] r_TxBDNum; // Receive buffer descriptor number + +// Interrupts +output TxB_IRQ; +output TxE_IRQ; +output RxB_IRQ; +output RxE_IRQ; +output Busy_IRQ; + + +// Bist +`ifdef ETH_BIST +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`ETH_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +reg TxB_IRQ; +reg TxE_IRQ; +reg RxB_IRQ; +reg RxE_IRQ; + +reg TxStartFrm; +reg TxEndFrm; +reg [7:0] TxData; + +reg TxUnderRun; +reg TxUnderRun_wb; + +reg TxBDRead; +wire TxStatusWrite; + +reg [1:0] TxValidBytesLatched; + +reg [15:0] TxLength; +reg [15:0] LatchedTxLength; +reg [14:11] TxStatus; + +reg [14:13] RxStatus; + +reg TxStartFrm_wb; +reg TxRetry_wb; +reg TxAbort_wb; +reg TxDone_wb; + +reg TxDone_wb_q; +reg TxAbort_wb_q; +reg TxRetry_wb_q; +reg TxRetryPacket; +reg TxRetryPacket_NotCleared; +reg TxDonePacket; +reg TxDonePacket_NotCleared; +reg TxAbortPacket; +reg TxAbortPacket_NotCleared; +reg RxBDReady; +reg RxReady; +reg TxBDReady; + +reg RxBDRead; + +reg [31:0] TxDataLatched; +reg [1:0] TxByteCnt; +reg LastWord; +reg ReadTxDataFromFifo_tck; + +reg BlockingTxStatusWrite; +reg BlockingTxBDRead; + +reg Flop; + +reg [7:1] TxBDAddress; +reg [7:1] RxBDAddress; + +reg TxRetrySync1; +reg TxAbortSync1; +reg TxDoneSync1; + +reg TxAbort_q; +reg TxRetry_q; +reg TxUsedData_q; + +reg [31:0] RxDataLatched2; + +reg [31:8] RxDataLatched1; // Big Endian Byte Ordering + +reg [1:0] RxValidBytes; +reg [1:0] RxByteCnt; +reg LastByteIn; +reg ShiftWillEnd; + +reg WriteRxDataToFifo; +reg [15:0] LatchedRxLength; +reg RxAbortLatched; + +reg ShiftEnded; +reg RxOverrun; + +reg [3:0] BDWrite; // BD Write Enable for access from WISHBONE side +reg BDRead; // BD Read access from WISHBONE side +wire [31:0] RxBDDataIn; // Rx BD data in +wire [31:0] TxBDDataIn; // Tx BD data in + +reg TxEndFrm_wb; + +wire TxRetryPulse; +wire TxDonePulse; +wire TxAbortPulse; + +wire StartRxBDRead; + +wire StartTxBDRead; + +wire TxIRQEn; +wire WrapTxStatusBit; + +wire RxIRQEn; +wire WrapRxStatusBit; + +wire [1:0] TxValidBytes; + +wire [7:1] TempTxBDAddress; +wire [7:1] TempRxBDAddress; + +wire RxStatusWrite; +wire RxBufferFull; +wire RxBufferAlmostEmpty; +wire RxBufferEmpty; + +reg WB_ACK_O; + +wire [8:0] RxStatusIn; +reg [8:0] RxStatusInLatched; + +reg WbEn, WbEn_q; +reg RxEn, RxEn_q; +reg TxEn, TxEn_q; +reg r_TxEn_q; +reg r_RxEn_q; + +wire ram_ce; +wire [3:0] ram_we; +wire ram_oe; +reg [7:0] ram_addr; +reg [31:0] ram_di; +wire [31:0] ram_do; + +wire StartTxPointerRead; +reg TxPointerRead; +reg TxEn_needed; +reg RxEn_needed; + +wire StartRxPointerRead; +reg RxPointerRead; + +`ifdef ETH_WISHBONE_B3 +assign m_wb_bte_o = 2'b00; // Linear burst +`endif + +assign m_wb_stb_o = m_wb_cyc_o; + +always @ (posedge WB_CLK_I) +begin + WB_ACK_O <=#Tp (|BDWrite) & WbEn & WbEn_q | BDRead & WbEn & ~WbEn_q; +end + +assign WB_DAT_O = ram_do; + +// Generic synchronous single-port RAM interface +eth_spram_256x32 bd_ram ( + .clk(WB_CLK_I), .rst(Reset), .ce(ram_ce), .we(ram_we), .oe(ram_oe), .addr(ram_addr), .di(ram_di), .do(ram_do) +`ifdef ETH_BIST + , + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +); + +assign ram_ce = 1'b1; +assign ram_we = (BDWrite & {4{(WbEn & WbEn_q)}}) | {4{(TxStatusWrite | RxStatusWrite)}}; +assign ram_oe = BDRead & WbEn & WbEn_q | TxEn & TxEn_q & (TxBDRead | TxPointerRead) | RxEn & RxEn_q & (RxBDRead | RxPointerRead); + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxEn_needed <=#Tp 1'b0; + else + if(~TxBDReady & r_TxEn & WbEn & ~WbEn_q) + TxEn_needed <=#Tp 1'b1; + else + if(TxPointerRead & TxEn & TxEn_q) + TxEn_needed <=#Tp 1'b0; +end + +// Enabling access to the RAM for three devices. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + begin + WbEn <=#Tp 1'b1; + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b0; + ram_addr <=#Tp 8'h0; + ram_di <=#Tp 32'h0; + BDRead <=#Tp 1'b0; + BDWrite <=#Tp 1'b0; + end + else + begin + // Switching between three stages depends on enable signals + case ({WbEn_q, RxEn_q, TxEn_q, RxEn_needed, TxEn_needed}) // synopsys parallel_case + 5'b100_10, 5'b100_11 : + begin + WbEn <=#Tp 1'b0; + RxEn <=#Tp 1'b1; // wb access stage and r_RxEn is enabled + TxEn <=#Tp 1'b0; + ram_addr <=#Tp {RxBDAddress, RxPointerRead}; + ram_di <=#Tp RxBDDataIn; + end + 5'b100_01 : + begin + WbEn <=#Tp 1'b0; + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b1; // wb access stage, r_RxEn is disabled but r_TxEn is enabled + ram_addr <=#Tp {TxBDAddress, TxPointerRead}; + ram_di <=#Tp TxBDDataIn; + end + 5'b010_00, 5'b010_10 : + begin + WbEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is disabled + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b0; + ram_addr <=#Tp WB_ADR_I[9:2]; + ram_di <=#Tp WB_DAT_I; + BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; + BDRead <=#Tp (|BDCs) & ~WB_WE_I; + end + 5'b010_01, 5'b010_11 : + begin + WbEn <=#Tp 1'b0; + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is enabled + ram_addr <=#Tp {TxBDAddress, TxPointerRead}; + ram_di <=#Tp TxBDDataIn; + end + 5'b001_00, 5'b001_01, 5'b001_10, 5'b001_11 : + begin + WbEn <=#Tp 1'b1; // TxEn access stage (we always go to wb access stage) + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b0; + ram_addr <=#Tp WB_ADR_I[9:2]; + ram_di <=#Tp WB_DAT_I; + BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; + BDRead <=#Tp (|BDCs) & ~WB_WE_I; + end + 5'b100_00 : + begin + WbEn <=#Tp 1'b0; // WbEn access stage and there is no need for other stages. WbEn needs to be switched off for a bit + end + 5'b000_00 : + begin + WbEn <=#Tp 1'b1; // Idle state. We go to WbEn access stage. + RxEn <=#Tp 1'b0; + TxEn <=#Tp 1'b0; + ram_addr <=#Tp WB_ADR_I[9:2]; + ram_di <=#Tp WB_DAT_I; + BDWrite <=#Tp BDCs[3:0] & {4{WB_WE_I}}; + BDRead <=#Tp (|BDCs) & ~WB_WE_I; + end + endcase + end +end + + +// Delayed stage signals +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + begin + WbEn_q <=#Tp 1'b0; + RxEn_q <=#Tp 1'b0; + TxEn_q <=#Tp 1'b0; + r_TxEn_q <=#Tp 1'b0; + r_RxEn_q <=#Tp 1'b0; + end + else + begin + WbEn_q <=#Tp WbEn; + RxEn_q <=#Tp RxEn; + TxEn_q <=#Tp TxEn; + r_TxEn_q <=#Tp r_TxEn; + r_RxEn_q <=#Tp r_RxEn; + end +end + +// Changes for tx occur every second clock. Flop is used for this manner. +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + Flop <=#Tp 1'b0; + else + if(TxDone | TxAbort | TxRetry_q) + Flop <=#Tp 1'b0; + else + if(TxUsedData) + Flop <=#Tp ~Flop; +end + +wire ResetTxBDReady; +assign ResetTxBDReady = TxDonePulse | TxAbortPulse | TxRetryPulse; + +// Latching READY status of the Tx buffer descriptor +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxBDReady <=#Tp 1'b0; + else + if(TxEn & TxEn_q & TxBDRead) + TxBDReady <=#Tp ram_do[15] & (ram_do[31:16] > 4); // TxBDReady is sampled only once at the beginning. + else // Only packets larger then 4 bytes are transmitted. + if(ResetTxBDReady) + TxBDReady <=#Tp 1'b0; +end + + +// Reading the Tx buffer descriptor +assign StartTxBDRead = (TxRetryPacket_NotCleared | TxStatusWrite) & ~BlockingTxBDRead & ~TxBDReady; + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxBDRead <=#Tp 1'b1; + else + if(StartTxBDRead) + TxBDRead <=#Tp 1'b1; + else + if(TxBDReady) + TxBDRead <=#Tp 1'b0; +end + + +// Reading Tx BD pointer +assign StartTxPointerRead = TxBDRead & TxBDReady; + +// Reading Tx BD Pointer +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxPointerRead <=#Tp 1'b0; + else + if(StartTxPointerRead) + TxPointerRead <=#Tp 1'b1; + else + if(TxEn_q) + TxPointerRead <=#Tp 1'b0; +end + + +// Writing status back to the Tx buffer descriptor +assign TxStatusWrite = (TxDonePacket_NotCleared | TxAbortPacket_NotCleared) & TxEn & TxEn_q & ~BlockingTxStatusWrite; + + + +// Status writing must occur only once. Meanwhile it is blocked. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + BlockingTxStatusWrite <=#Tp 1'b0; + else + if(~TxDone_wb & ~TxAbort_wb) + BlockingTxStatusWrite <=#Tp 1'b0; + else + if(TxStatusWrite) + BlockingTxStatusWrite <=#Tp 1'b1; +end + + +reg BlockingTxStatusWrite_sync1; +reg BlockingTxStatusWrite_sync2; +reg BlockingTxStatusWrite_sync3; + +// Synchronizing BlockingTxStatusWrite to MTxClk +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + BlockingTxStatusWrite_sync1 <=#Tp 1'b0; + else + BlockingTxStatusWrite_sync1 <=#Tp BlockingTxStatusWrite; +end + +// Synchronizing BlockingTxStatusWrite to MTxClk +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + BlockingTxStatusWrite_sync2 <=#Tp 1'b0; + else + BlockingTxStatusWrite_sync2 <=#Tp BlockingTxStatusWrite_sync1; +end + +// Synchronizing BlockingTxStatusWrite to MTxClk +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + BlockingTxStatusWrite_sync3 <=#Tp 1'b0; + else + BlockingTxStatusWrite_sync3 <=#Tp BlockingTxStatusWrite_sync2; +end + +assign RstDeferLatched = BlockingTxStatusWrite_sync2 & ~BlockingTxStatusWrite_sync3; + +// TxBDRead state is activated only once. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + BlockingTxBDRead <=#Tp 1'b0; + else + if(StartTxBDRead) + BlockingTxBDRead <=#Tp 1'b1; + else + if(~StartTxBDRead & ~TxBDReady) + BlockingTxBDRead <=#Tp 1'b0; +end + + +// Latching status from the tx buffer descriptor +// Data is avaliable one cycle after the access is started (at that time signal TxEn is not active) +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxStatus <=#Tp 4'h0; + else + if(TxEn & TxEn_q & TxBDRead) + TxStatus <=#Tp ram_do[14:11]; +end + +reg ReadTxDataFromMemory; +wire WriteRxDataToMemory; + +reg MasterWbTX; +reg MasterWbRX; + +reg [29:0] m_wb_adr_o; +reg m_wb_cyc_o; +reg [3:0] m_wb_sel_o; +reg m_wb_we_o; + +wire TxLengthEq0; +wire TxLengthLt4; + +reg BlockingIncrementTxPointer; +reg [31:2] TxPointerMSB; +reg [1:0] TxPointerLSB; +reg [1:0] TxPointerLSB_rst; +reg [31:2] RxPointerMSB; +reg [1:0] RxPointerLSB_rst; + +wire RxBurstAcc; +wire RxWordAcc; +wire RxHalfAcc; +wire RxByteAcc; + +//Latching length from the buffer descriptor; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxLength <=#Tp 16'h0; + else + if(TxEn & TxEn_q & TxBDRead) + TxLength <=#Tp ram_do[31:16]; + else + if(MasterWbTX & m_wb_ack_i) + begin + if(TxLengthLt4) + TxLength <=#Tp 16'h0; + else + if(TxPointerLSB_rst==2'h0) + TxLength <=#Tp TxLength - 3'h4; // Length is subtracted at the data request + else + if(TxPointerLSB_rst==2'h1) + TxLength <=#Tp TxLength - 3'h3; // Length is subtracted at the data request + else + if(TxPointerLSB_rst==2'h2) + TxLength <=#Tp TxLength - 3'h2; // Length is subtracted at the data request + else + if(TxPointerLSB_rst==2'h3) + TxLength <=#Tp TxLength - 3'h1; // Length is subtracted at the data request + end +end + + + +//Latching length from the buffer descriptor; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + LatchedTxLength <=#Tp 16'h0; + else + if(TxEn & TxEn_q & TxBDRead) + LatchedTxLength <=#Tp ram_do[31:16]; +end + +assign TxLengthEq0 = TxLength == 0; +assign TxLengthLt4 = TxLength < 4; + +reg cyc_cleared; +reg IncrTxPointer; + + +// Latching Tx buffer pointer from buffer descriptor. Only 30 MSB bits are latched +// because TxPointerMSB is only used for word-aligned accesses. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxPointerMSB <=#Tp 30'h0; + else + if(TxEn & TxEn_q & TxPointerRead) + TxPointerMSB <=#Tp ram_do[31:2]; + else + if(IncrTxPointer & ~BlockingIncrementTxPointer) + TxPointerMSB <=#Tp TxPointerMSB + 1'b1; // TxPointer is word-aligned +end + + +// Latching 2 MSB bits of the buffer descriptor. Since word accesses are performed, +// valid data does not necesserly start at byte 0 (could be byte 0, 1, 2 or 3). This +// signals are used for proper selection of the start byte (TxData and TxByteCnt) are +// set by this two bits. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxPointerLSB[1:0] <=#Tp 0; + else + if(TxEn & TxEn_q & TxPointerRead) + TxPointerLSB[1:0] <=#Tp ram_do[1:0]; +end + + +// Latching 2 MSB bits of the buffer descriptor. +// After the read access, TxLength needs to be decremented for the number of the valid +// bytes (1 to 4 bytes are valid in the first word). After the first read all bytes are +// valid so this two bits are reset to zero. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxPointerLSB_rst[1:0] <=#Tp 0; + else + if(TxEn & TxEn_q & TxPointerRead) + TxPointerLSB_rst[1:0] <=#Tp ram_do[1:0]; + else + if(MasterWbTX & m_wb_ack_i) // After first access pointer is word alligned + TxPointerLSB_rst[1:0] <=#Tp 0; +end + + +reg [3:0] RxByteSel; +wire MasterAccessFinished; + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + BlockingIncrementTxPointer <=#Tp 0; + else + if(MasterAccessFinished) + BlockingIncrementTxPointer <=#Tp 0; + else + if(IncrTxPointer) + BlockingIncrementTxPointer <=#Tp 1'b1; +end + + +wire TxBufferAlmostFull; +wire TxBufferFull; +wire TxBufferEmpty; +wire TxBufferAlmostEmpty; +wire SetReadTxDataFromMemory; + +reg BlockReadTxDataFromMemory; + +assign SetReadTxDataFromMemory = TxEn & TxEn_q & TxPointerRead; + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ReadTxDataFromMemory <=#Tp 1'b0; + else + if(TxLengthEq0 | TxAbortPulse | TxRetryPulse) + ReadTxDataFromMemory <=#Tp 1'b0; + else + if(SetReadTxDataFromMemory) + ReadTxDataFromMemory <=#Tp 1'b1; +end + +reg tx_burst_en; +reg rx_burst_en; + +wire ReadTxDataFromMemory_2 = ReadTxDataFromMemory & ~BlockReadTxDataFromMemory; +wire tx_burst = ReadTxDataFromMemory_2 & tx_burst_en; + +wire [31:0] TxData_wb; +wire ReadTxDataFromFifo_wb; + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + BlockReadTxDataFromMemory <=#Tp 1'b0; + else + if((TxBufferAlmostFull | TxLength <= 4)& MasterWbTX & (~cyc_cleared) & (!(TxAbortPacket_NotCleared | TxRetryPacket_NotCleared))) + BlockReadTxDataFromMemory <=#Tp 1'b1; + else + if(ReadTxDataFromFifo_wb | TxDonePacket | TxAbortPacket | TxRetryPacket) + BlockReadTxDataFromMemory <=#Tp 1'b0; +end + + +assign MasterAccessFinished = m_wb_ack_i | m_wb_err_i; +wire [`ETH_TX_FIFO_CNT_WIDTH-1:0] txfifo_cnt; +wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rxfifo_cnt; +reg [`ETH_BURST_CNT_WIDTH-1:0] tx_burst_cnt; +reg [`ETH_BURST_CNT_WIDTH-1:0] rx_burst_cnt; + +wire rx_burst; +wire enough_data_in_rxfifo_for_burst; +wire enough_data_in_rxfifo_for_burst_plus1; + +// Enabling master wishbone access to the memory for two devices TX and RX. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + begin + MasterWbTX <=#Tp 1'b0; + MasterWbRX <=#Tp 1'b0; + m_wb_adr_o <=#Tp 30'h0; + m_wb_cyc_o <=#Tp 1'b0; + m_wb_we_o <=#Tp 1'b0; + m_wb_sel_o <=#Tp 4'h0; + cyc_cleared<=#Tp 1'b0; + tx_burst_cnt<=#Tp 0; + rx_burst_cnt<=#Tp 0; + IncrTxPointer<=#Tp 1'b0; + tx_burst_en<=#Tp 1'b1; + rx_burst_en<=#Tp 1'b0; + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b0; + `endif + end + else + begin + // Switching between two stages depends on enable signals + casex ({MasterWbTX, MasterWbRX, ReadTxDataFromMemory_2, WriteRxDataToMemory, MasterAccessFinished, cyc_cleared, tx_burst, rx_burst}) // synopsys parallel_case + 8'b00_10_00_10, // Idle and MRB needed + 8'b10_1x_10_1x, // MRB continues + 8'b10_10_01_10, // Clear (previously MR) and MRB needed + 8'b01_1x_01_1x : // Clear (previously MW) and MRB needed + begin + MasterWbTX <=#Tp 1'b1; // tx burst + MasterWbRX <=#Tp 1'b0; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b0; + m_wb_sel_o <=#Tp 4'hf; + cyc_cleared<=#Tp 1'b0; + IncrTxPointer<=#Tp 1'b1; + tx_burst_cnt <=#Tp tx_burst_cnt+3'h1; + if(tx_burst_cnt==0) + m_wb_adr_o <=#Tp TxPointerMSB; + else + m_wb_adr_o <=#Tp m_wb_adr_o+1'b1; + + if(tx_burst_cnt==(`ETH_BURST_LENGTH-1)) + begin + tx_burst_en<=#Tp 1'b0; + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b111; + `endif + end + else + begin + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b010; + `endif + end + end + 8'b00_x1_00_x1, // Idle and MWB needed + 8'b01_x1_10_x1, // MWB continues + 8'b01_01_01_01, // Clear (previously MW) and MWB needed + 8'b10_x1_01_x1 : // Clear (previously MR) and MWB needed + begin + MasterWbTX <=#Tp 1'b0; // rx burst + MasterWbRX <=#Tp 1'b1; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b1; + m_wb_sel_o <=#Tp RxByteSel; + IncrTxPointer<=#Tp 1'b0; + cyc_cleared<=#Tp 1'b0; + rx_burst_cnt <=#Tp rx_burst_cnt+3'h1; + + if(rx_burst_cnt==0) + m_wb_adr_o <=#Tp RxPointerMSB; + else + m_wb_adr_o <=#Tp m_wb_adr_o+1'b1; + + if(rx_burst_cnt==(`ETH_BURST_LENGTH-1)) + begin + rx_burst_en<=#Tp 1'b0; + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b111; + `endif + end + else + begin + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b010; + `endif + end + end + 8'b00_x1_00_x0 : // idle and MW is needed (data write to rx buffer) + begin + MasterWbTX <=#Tp 1'b0; + MasterWbRX <=#Tp 1'b1; + m_wb_adr_o <=#Tp RxPointerMSB; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b1; + m_wb_sel_o <=#Tp RxByteSel; + IncrTxPointer<=#Tp 1'b0; + end + 8'b00_10_00_00 : // idle and MR is needed (data read from tx buffer) + begin + MasterWbTX <=#Tp 1'b1; + MasterWbRX <=#Tp 1'b0; + m_wb_adr_o <=#Tp TxPointerMSB; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b0; + m_wb_sel_o <=#Tp 4'hf; + IncrTxPointer<=#Tp 1'b1; + end + 8'b10_10_01_00, // MR and MR is needed (data read from tx buffer) + 8'b01_1x_01_0x : // MW and MR is needed (data read from tx buffer) + begin + MasterWbTX <=#Tp 1'b1; + MasterWbRX <=#Tp 1'b0; + m_wb_adr_o <=#Tp TxPointerMSB; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b0; + m_wb_sel_o <=#Tp 4'hf; + cyc_cleared<=#Tp 1'b0; + IncrTxPointer<=#Tp 1'b1; + end + 8'b01_01_01_00, // MW and MW needed (data write to rx buffer) + 8'b10_x1_01_x0 : // MR and MW is needed (data write to rx buffer) + begin + MasterWbTX <=#Tp 1'b0; + MasterWbRX <=#Tp 1'b1; + m_wb_adr_o <=#Tp RxPointerMSB; + m_wb_cyc_o <=#Tp 1'b1; + m_wb_we_o <=#Tp 1'b1; + m_wb_sel_o <=#Tp RxByteSel; + cyc_cleared<=#Tp 1'b0; + IncrTxPointer<=#Tp 1'b0; + end + 8'b01_01_10_00, // MW and MW needed (cycle is cleared between previous and next access) + 8'b01_1x_10_x0, // MW and MW or MR or MRB needed (cycle is cleared between previous and next access) + 8'b10_10_10_00, // MR and MR needed (cycle is cleared between previous and next access) + 8'b10_x1_10_0x : // MR and MR or MW or MWB (cycle is cleared between previous and next access) + begin + m_wb_cyc_o <=#Tp 1'b0; // whatever and master read or write is needed. We need to clear m_wb_cyc_o before next access is started + cyc_cleared<=#Tp 1'b1; + IncrTxPointer<=#Tp 1'b0; + tx_burst_cnt<=#Tp 0; + tx_burst_en<=#Tp txfifo_cnt<(`ETH_TX_FIFO_DEPTH-`ETH_BURST_LENGTH) & (TxLength>(`ETH_BURST_LENGTH*4+4)); + rx_burst_cnt<=#Tp 0; + rx_burst_en<=#Tp MasterWbRX ? enough_data_in_rxfifo_for_burst_plus1 : enough_data_in_rxfifo_for_burst; // Counter is not decremented, yet, so plus1 is used. + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b0; + `endif + end + 8'bxx_00_10_00, // whatever and no master read or write is needed (ack or err comes finishing previous access) + 8'bxx_00_01_00 : // Between cyc_cleared request was cleared + begin + MasterWbTX <=#Tp 1'b0; + MasterWbRX <=#Tp 1'b0; + m_wb_cyc_o <=#Tp 1'b0; + cyc_cleared<=#Tp 1'b0; + IncrTxPointer<=#Tp 1'b0; + rx_burst_cnt<=#Tp 0; + rx_burst_en<=#Tp MasterWbRX ? enough_data_in_rxfifo_for_burst_plus1 : enough_data_in_rxfifo_for_burst; // Counter is not decremented, yet, so plus1 is used. + `ifdef ETH_WISHBONE_B3 + m_wb_cti_o <=#Tp 3'b0; + `endif + end + 8'b00_00_00_00: // whatever and no master read or write is needed (ack or err comes finishing previous access) + begin + tx_burst_cnt<=#Tp 0; + tx_burst_en<=#Tp txfifo_cnt<(`ETH_TX_FIFO_DEPTH-`ETH_BURST_LENGTH) & (TxLength>(`ETH_BURST_LENGTH*4+4)); + end + default: // Don't touch + begin + MasterWbTX <=#Tp MasterWbTX; + MasterWbRX <=#Tp MasterWbRX; + m_wb_cyc_o <=#Tp m_wb_cyc_o; + m_wb_sel_o <=#Tp m_wb_sel_o; + IncrTxPointer<=#Tp IncrTxPointer; + end + endcase + end +end + + +wire TxFifoClear; + +assign TxFifoClear = (TxAbortPacket | TxRetryPacket); + +eth_fifo #(`ETH_TX_FIFO_DATA_WIDTH, `ETH_TX_FIFO_DEPTH, `ETH_TX_FIFO_CNT_WIDTH) +tx_fifo ( .data_in(m_wb_dat_i), .data_out(TxData_wb), + .clk(WB_CLK_I), .reset(Reset), + .write(MasterWbTX & m_wb_ack_i), .read(ReadTxDataFromFifo_wb & ~TxBufferEmpty), + .clear(TxFifoClear), .full(TxBufferFull), + .almost_full(TxBufferAlmostFull), .almost_empty(TxBufferAlmostEmpty), + .empty(TxBufferEmpty), .cnt(txfifo_cnt) + ); + + +reg StartOccured; +reg TxStartFrm_sync1; +reg TxStartFrm_sync2; +reg TxStartFrm_syncb1; +reg TxStartFrm_syncb2; + + + +// Start: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxStartFrm_wb <=#Tp 1'b0; + else + if(TxBDReady & ~StartOccured & (TxBufferFull | TxLengthEq0)) + TxStartFrm_wb <=#Tp 1'b1; + else + if(TxStartFrm_syncb2) + TxStartFrm_wb <=#Tp 1'b0; +end + +// StartOccured: TxStartFrm_wb occurs only ones at the beginning. Then it's blocked. +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + StartOccured <=#Tp 1'b0; + else + if(TxStartFrm_wb) + StartOccured <=#Tp 1'b1; + else + if(ResetTxBDReady) + StartOccured <=#Tp 1'b0; +end + +// Synchronizing TxStartFrm_wb to MTxClk +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxStartFrm_sync1 <=#Tp 1'b0; + else + TxStartFrm_sync1 <=#Tp TxStartFrm_wb; +end + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxStartFrm_sync2 <=#Tp 1'b0; + else + TxStartFrm_sync2 <=#Tp TxStartFrm_sync1; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxStartFrm_syncb1 <=#Tp 1'b0; + else + TxStartFrm_syncb1 <=#Tp TxStartFrm_sync2; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxStartFrm_syncb2 <=#Tp 1'b0; + else + TxStartFrm_syncb2 <=#Tp TxStartFrm_syncb1; +end + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxStartFrm <=#Tp 1'b0; + else + if(TxStartFrm_sync2) + TxStartFrm <=#Tp 1'b1; + else + if(TxUsedData_q | ~TxStartFrm_sync2 & (TxRetry & (~TxRetry_q) | TxAbort & (~TxAbort_q))) + TxStartFrm <=#Tp 1'b0; +end +// End: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk + + +// TxEndFrm_wb: indicator of the end of frame +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxEndFrm_wb <=#Tp 1'b0; + else + if(TxLengthEq0 & TxBufferAlmostEmpty & TxUsedData) + TxEndFrm_wb <=#Tp 1'b1; + else + if(TxRetryPulse | TxDonePulse | TxAbortPulse) + TxEndFrm_wb <=#Tp 1'b0; +end + + +// Marks which bytes are valid within the word. +assign TxValidBytes = TxLengthLt4 ? TxLength[1:0] : 2'b0; + +reg LatchValidBytes; +reg LatchValidBytes_q; + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + LatchValidBytes <=#Tp 1'b0; + else + if(TxLengthLt4 & TxBDReady) + LatchValidBytes <=#Tp 1'b1; + else + LatchValidBytes <=#Tp 1'b0; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + LatchValidBytes_q <=#Tp 1'b0; + else + LatchValidBytes_q <=#Tp LatchValidBytes; +end + + +// Latching valid bytes +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxValidBytesLatched <=#Tp 2'h0; + else + if(LatchValidBytes & ~LatchValidBytes_q) + TxValidBytesLatched <=#Tp TxValidBytes; + else + if(TxRetryPulse | TxDonePulse | TxAbortPulse) + TxValidBytesLatched <=#Tp 2'h0; +end + + +assign TxIRQEn = TxStatus[14]; +assign WrapTxStatusBit = TxStatus[13]; +assign PerPacketPad = TxStatus[12]; +assign PerPacketCrcEn = TxStatus[11]; + + +assign RxIRQEn = RxStatus[14]; +assign WrapRxStatusBit = RxStatus[13]; + + +// Temporary Tx and Rx buffer descriptor address +assign TempTxBDAddress[7:1] = {7{ TxStatusWrite & ~WrapTxStatusBit}} & (TxBDAddress + 1'b1) ; // Tx BD increment or wrap (last BD) +assign TempRxBDAddress[7:1] = {7{ WrapRxStatusBit}} & (r_TxBDNum[6:0]) | // Using first Rx BD + {7{~WrapRxStatusBit}} & (RxBDAddress + 1'b1) ; // Using next Rx BD (incremenrement address) + + +// Latching Tx buffer descriptor address +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxBDAddress <=#Tp 7'h0; + else if (r_TxEn & (~r_TxEn_q)) + TxBDAddress <=#Tp 7'h0; + else if (TxStatusWrite) + TxBDAddress <=#Tp TempTxBDAddress; +end + + +// Latching Rx buffer descriptor address +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxBDAddress <=#Tp 7'h0; + else if(r_RxEn & (~r_RxEn_q)) + RxBDAddress <=#Tp r_TxBDNum[6:0]; + else if(RxStatusWrite) + RxBDAddress <=#Tp TempRxBDAddress; +end + +wire [8:0] TxStatusInLatched = {TxUnderRun, RetryCntLatched[3:0], RetryLimit, LateCollLatched, DeferLatched, CarrierSenseLost}; + +assign RxBDDataIn = {LatchedRxLength, 1'b0, RxStatus, 4'h0, RxStatusInLatched}; +assign TxBDDataIn = {LatchedTxLength, 1'b0, TxStatus, 2'h0, TxStatusInLatched}; + + +// Signals used for various purposes +assign TxRetryPulse = TxRetry_wb & ~TxRetry_wb_q; +assign TxDonePulse = TxDone_wb & ~TxDone_wb_q; +assign TxAbortPulse = TxAbort_wb & ~TxAbort_wb_q; + + + +// Generating delayed signals +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + begin + TxAbort_q <=#Tp 1'b0; + TxRetry_q <=#Tp 1'b0; + TxUsedData_q <=#Tp 1'b0; + end + else + begin + TxAbort_q <=#Tp TxAbort; + TxRetry_q <=#Tp TxRetry; + TxUsedData_q <=#Tp TxUsedData; + end +end + +// Generating delayed signals +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + begin + TxDone_wb_q <=#Tp 1'b0; + TxAbort_wb_q <=#Tp 1'b0; + TxRetry_wb_q <=#Tp 1'b0; + end + else + begin + TxDone_wb_q <=#Tp TxDone_wb; + TxAbort_wb_q <=#Tp TxAbort_wb; + TxRetry_wb_q <=#Tp TxRetry_wb; + end +end + + +reg TxAbortPacketBlocked; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxAbortPacket <=#Tp 1'b0; + else + if(TxAbort_wb & (~tx_burst_en) & MasterWbTX & MasterAccessFinished & (~TxAbortPacketBlocked) | + TxAbort_wb & (~MasterWbTX) & (~TxAbortPacketBlocked)) + TxAbortPacket <=#Tp 1'b1; + else + TxAbortPacket <=#Tp 1'b0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxAbortPacket_NotCleared <=#Tp 1'b0; + else + if(TxEn & TxEn_q & TxAbortPacket_NotCleared) + TxAbortPacket_NotCleared <=#Tp 1'b0; + else + if(TxAbort_wb & (~tx_burst_en) & MasterWbTX & MasterAccessFinished & (~TxAbortPacketBlocked) | + TxAbort_wb & (~MasterWbTX) & (~TxAbortPacketBlocked)) + TxAbortPacket_NotCleared <=#Tp 1'b1; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxAbortPacketBlocked <=#Tp 1'b0; + else + if(!TxAbort_wb & TxAbort_wb_q) + TxAbortPacketBlocked <=#Tp 1'b0; + else + if(TxAbortPacket) + TxAbortPacketBlocked <=#Tp 1'b1; +end + + +reg TxRetryPacketBlocked; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxRetryPacket <=#Tp 1'b0; + else + if(TxRetry_wb & !tx_burst_en & MasterWbTX & MasterAccessFinished & !TxRetryPacketBlocked | + TxRetry_wb & !MasterWbTX & !TxRetryPacketBlocked) + TxRetryPacket <=#Tp 1'b1; + else + TxRetryPacket <=#Tp 1'b0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxRetryPacket_NotCleared <=#Tp 1'b0; + else + if(StartTxBDRead) + TxRetryPacket_NotCleared <=#Tp 1'b0; + else + if(TxRetry_wb & !tx_burst_en & MasterWbTX & MasterAccessFinished & !TxRetryPacketBlocked | + TxRetry_wb & !MasterWbTX & !TxRetryPacketBlocked) + TxRetryPacket_NotCleared <=#Tp 1'b1; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxRetryPacketBlocked <=#Tp 1'b0; + else + if(!TxRetry_wb & TxRetry_wb_q) + TxRetryPacketBlocked <=#Tp 1'b0; + else + if(TxRetryPacket) + TxRetryPacketBlocked <=#Tp 1'b1; +end + + +reg TxDonePacketBlocked; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxDonePacket <=#Tp 1'b0; + else + if(TxDone_wb & !tx_burst_en & MasterWbTX & MasterAccessFinished & !TxDonePacketBlocked | + TxDone_wb & !MasterWbTX & !TxDonePacketBlocked) + TxDonePacket <=#Tp 1'b1; + else + TxDonePacket <=#Tp 1'b0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxDonePacket_NotCleared <=#Tp 1'b0; + else + if(TxEn & TxEn_q & TxDonePacket_NotCleared) + TxDonePacket_NotCleared <=#Tp 1'b0; + else + if(TxDone_wb & !tx_burst_en & MasterWbTX & MasterAccessFinished & (~TxDonePacketBlocked) | + TxDone_wb & !MasterWbTX & (~TxDonePacketBlocked)) + TxDonePacket_NotCleared <=#Tp 1'b1; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxDonePacketBlocked <=#Tp 1'b0; + else + if(!TxDone_wb & TxDone_wb_q) + TxDonePacketBlocked <=#Tp 1'b0; + else + if(TxDonePacket) + TxDonePacketBlocked <=#Tp 1'b1; +end + + +// Indication of the last word +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + LastWord <=#Tp 1'b0; + else + if((TxEndFrm | TxAbort | TxRetry) & Flop) + LastWord <=#Tp 1'b0; + else + if(TxUsedData & Flop & TxByteCnt == 2'h3) + LastWord <=#Tp TxEndFrm_wb; +end + + +// Tx end frame generation +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxEndFrm <=#Tp 1'b0; + else + if(Flop & TxEndFrm | TxAbort | TxRetry_q) + TxEndFrm <=#Tp 1'b0; + else + if(Flop & LastWord) + begin + case (TxValidBytesLatched) // synopsys parallel_case + 1 : TxEndFrm <=#Tp TxByteCnt == 2'h0; + 2 : TxEndFrm <=#Tp TxByteCnt == 2'h1; + 3 : TxEndFrm <=#Tp TxByteCnt == 2'h2; + 0 : TxEndFrm <=#Tp TxByteCnt == 2'h3; + default : TxEndFrm <=#Tp 1'b0; + endcase + end +end + + +// Tx data selection (latching) +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxData <=#Tp 0; + else + if(TxStartFrm_sync2 & ~TxStartFrm) + case(TxPointerLSB) // synopsys parallel_case + 2'h0 : TxData <=#Tp TxData_wb[31:24]; // Big Endian Byte Ordering + 2'h1 : TxData <=#Tp TxData_wb[23:16]; // Big Endian Byte Ordering + 2'h2 : TxData <=#Tp TxData_wb[15:08]; // Big Endian Byte Ordering + 2'h3 : TxData <=#Tp TxData_wb[07:00]; // Big Endian Byte Ordering + endcase + else + if(TxStartFrm & TxUsedData & TxPointerLSB==2'h3) + TxData <=#Tp TxData_wb[31:24]; // Big Endian Byte Ordering + else + if(TxUsedData & Flop) + begin + case(TxByteCnt) // synopsys parallel_case + 0 : TxData <=#Tp TxDataLatched[31:24]; // Big Endian Byte Ordering + 1 : TxData <=#Tp TxDataLatched[23:16]; + 2 : TxData <=#Tp TxDataLatched[15:8]; + 3 : TxData <=#Tp TxDataLatched[7:0]; + endcase + end +end + + +// Latching tx data +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxDataLatched[31:0] <=#Tp 32'h0; + else + if(TxStartFrm_sync2 & ~TxStartFrm | TxUsedData & Flop & TxByteCnt == 2'h3 | TxStartFrm & TxUsedData & Flop & TxByteCnt == 2'h0) + TxDataLatched[31:0] <=#Tp TxData_wb[31:0]; +end + + +// Tx under run +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxUnderRun_wb <=#Tp 1'b0; + else + if(TxAbortPulse) + TxUnderRun_wb <=#Tp 1'b0; + else + if(TxBufferEmpty & ReadTxDataFromFifo_wb) + TxUnderRun_wb <=#Tp 1'b1; +end + + +reg TxUnderRun_sync1; + +// Tx under run +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxUnderRun_sync1 <=#Tp 1'b0; + else + if(TxUnderRun_wb) + TxUnderRun_sync1 <=#Tp 1'b1; + else + if(BlockingTxStatusWrite_sync2) + TxUnderRun_sync1 <=#Tp 1'b0; +end + +// Tx under run +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxUnderRun <=#Tp 1'b0; + else + if(BlockingTxStatusWrite_sync2) + TxUnderRun <=#Tp 1'b0; + else + if(TxUnderRun_sync1) + TxUnderRun <=#Tp 1'b1; +end + + +// Tx Byte counter +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + TxByteCnt <=#Tp 2'h0; + else + if(TxAbort_q | TxRetry_q) + TxByteCnt <=#Tp 2'h0; + else + if(TxStartFrm & ~TxUsedData) + case(TxPointerLSB) // synopsys parallel_case + 2'h0 : TxByteCnt <=#Tp 2'h1; + 2'h1 : TxByteCnt <=#Tp 2'h2; + 2'h2 : TxByteCnt <=#Tp 2'h3; + 2'h3 : TxByteCnt <=#Tp 2'h0; + endcase + else + if(TxUsedData & Flop) + TxByteCnt <=#Tp TxByteCnt + 1'b1; +end + + +// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I +reg ReadTxDataFromFifo_sync1; +reg ReadTxDataFromFifo_sync2; +reg ReadTxDataFromFifo_sync3; +reg ReadTxDataFromFifo_syncb1; +reg ReadTxDataFromFifo_syncb2; +reg ReadTxDataFromFifo_syncb3; + + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_tck <=#Tp 1'b0; + else + if(TxStartFrm_sync2 & ~TxStartFrm | TxUsedData & Flop & TxByteCnt == 2'h3 & ~LastWord | TxStartFrm & TxUsedData & Flop & TxByteCnt == 2'h0) + ReadTxDataFromFifo_tck <=#Tp 1'b1; + else + if(ReadTxDataFromFifo_syncb2 & ~ReadTxDataFromFifo_syncb3) + ReadTxDataFromFifo_tck <=#Tp 1'b0; +end + +// Synchronizing TxStartFrm_wb to MTxClk +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_sync1 <=#Tp 1'b0; + else + ReadTxDataFromFifo_sync1 <=#Tp ReadTxDataFromFifo_tck; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_sync2 <=#Tp 1'b0; + else + ReadTxDataFromFifo_sync2 <=#Tp ReadTxDataFromFifo_sync1; +end + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_syncb1 <=#Tp 1'b0; + else + ReadTxDataFromFifo_syncb1 <=#Tp ReadTxDataFromFifo_sync2; +end + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_syncb2 <=#Tp 1'b0; + else + ReadTxDataFromFifo_syncb2 <=#Tp ReadTxDataFromFifo_syncb1; +end + +always @ (posedge MTxClk or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_syncb3 <=#Tp 1'b0; + else + ReadTxDataFromFifo_syncb3 <=#Tp ReadTxDataFromFifo_syncb2; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ReadTxDataFromFifo_sync3 <=#Tp 1'b0; + else + ReadTxDataFromFifo_sync3 <=#Tp ReadTxDataFromFifo_sync2; +end + +assign ReadTxDataFromFifo_wb = ReadTxDataFromFifo_sync2 & ~ReadTxDataFromFifo_sync3; +// End: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I + + +// Synchronizing TxRetry signal (synchronized to WISHBONE clock) +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxRetrySync1 <=#Tp 1'b0; + else + TxRetrySync1 <=#Tp TxRetry; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxRetry_wb <=#Tp 1'b0; + else + TxRetry_wb <=#Tp TxRetrySync1; +end + + +// Synchronized TxDone_wb signal (synchronized to WISHBONE clock) +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxDoneSync1 <=#Tp 1'b0; + else + TxDoneSync1 <=#Tp TxDone; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxDone_wb <=#Tp 1'b0; + else + TxDone_wb <=#Tp TxDoneSync1; +end + +// Synchronizing TxAbort signal (synchronized to WISHBONE clock) +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxAbortSync1 <=#Tp 1'b0; + else + TxAbortSync1 <=#Tp TxAbort; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxAbort_wb <=#Tp 1'b0; + else + TxAbort_wb <=#Tp TxAbortSync1; +end + + +reg RxAbortSync1; +reg RxAbortSync2; +reg RxAbortSync3; +reg RxAbortSync4; +reg RxAbortSyncb1; +reg RxAbortSyncb2; + +assign StartRxBDRead = RxStatusWrite | RxAbortSync3 & ~RxAbortSync4 | r_RxEn & ~r_RxEn_q; + +// Reading the Rx buffer descriptor +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxBDRead <=#Tp 1'b0; + else + if(StartRxBDRead & ~RxReady) + RxBDRead <=#Tp 1'b1; + else + if(RxBDReady) + RxBDRead <=#Tp 1'b0; +end + + +// Reading of the next receive buffer descriptor starts after reception status is +// written to the previous one. + +// Latching READY status of the Rx buffer descriptor +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxBDReady <=#Tp 1'b0; + else + if(RxPointerRead) + RxBDReady <=#Tp 1'b0; + else + if(RxEn & RxEn_q & RxBDRead) + RxBDReady <=#Tp ram_do[15]; // RxBDReady is sampled only once at the beginning +end + +// Latching Rx buffer descriptor status +// Data is avaliable one cycle after the access is started (at that time signal RxEn is not active) +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxStatus <=#Tp 2'h0; + else + if(RxEn & RxEn_q & RxBDRead) + RxStatus <=#Tp ram_do[14:13]; +end + + +// RxReady generation +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxReady <=#Tp 1'b0; + else + if(ShiftEnded | RxAbortSync2 & ~RxAbortSync3 | ~r_RxEn & r_RxEn_q) + RxReady <=#Tp 1'b0; + else + if(RxEn & RxEn_q & RxPointerRead) + RxReady <=#Tp 1'b1; +end + + +// Reading Rx BD pointer + + +assign StartRxPointerRead = RxBDRead & RxBDReady; + +// Reading Tx BD Pointer +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxPointerRead <=#Tp 1'b0; + else + if(StartRxPointerRead) + RxPointerRead <=#Tp 1'b1; + else + if(RxEn & RxEn_q) + RxPointerRead <=#Tp 1'b0; +end + + +//Latching Rx buffer pointer from buffer descriptor; +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxPointerMSB <=#Tp 30'h0; + else + if(RxEn & RxEn_q & RxPointerRead) + RxPointerMSB <=#Tp ram_do[31:2]; + else + if(MasterWbRX & m_wb_ack_i) + RxPointerMSB <=#Tp RxPointerMSB + 1'b1; // Word access (always word access. m_wb_sel_o are used for selecting bytes) +end + + +//Latching last addresses from buffer descriptor (used as byte-half-word indicator); +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxPointerLSB_rst[1:0] <=#Tp 0; + else + if(MasterWbRX & m_wb_ack_i) // After first write all RxByteSel are active + RxPointerLSB_rst[1:0] <=#Tp 0; + else + if(RxEn & RxEn_q & RxPointerRead) + RxPointerLSB_rst[1:0] <=#Tp ram_do[1:0]; +end + + +always @ (RxPointerLSB_rst) +begin + case(RxPointerLSB_rst[1:0]) // synopsys parallel_case + 2'h0 : RxByteSel[3:0] = 4'hf; + 2'h1 : RxByteSel[3:0] = 4'h7; + 2'h2 : RxByteSel[3:0] = 4'h3; + 2'h3 : RxByteSel[3:0] = 4'h1; + endcase +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxEn_needed <=#Tp 1'b0; + else + if(~RxReady & r_RxEn & WbEn & ~WbEn_q) + RxEn_needed <=#Tp 1'b1; + else + if(RxPointerRead & RxEn & RxEn_q) + RxEn_needed <=#Tp 1'b0; +end + + +// Reception status is written back to the buffer descriptor after the end of frame is detected. +assign RxStatusWrite = ShiftEnded & RxEn & RxEn_q; + +reg RxEnableWindow; + +// Indicating that last byte is being reveived +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LastByteIn <=#Tp 1'b0; + else + if(ShiftWillEnd & (&RxByteCnt) | RxAbort) + LastByteIn <=#Tp 1'b0; + else + if(RxValid & RxReady & RxEndFrm & ~(&RxByteCnt) & RxEnableWindow) + LastByteIn <=#Tp 1'b1; +end + +reg ShiftEnded_rck; +reg ShiftEndedSync1; +reg ShiftEndedSync2; +reg ShiftEndedSync3; +reg ShiftEndedSync_c1; +reg ShiftEndedSync_c2; + +wire StartShiftWillEnd; +assign StartShiftWillEnd = LastByteIn | RxValid & RxEndFrm & (&RxByteCnt) & RxEnableWindow; + +// Indicating that data reception will end +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ShiftWillEnd <=#Tp 1'b0; + else + if(ShiftEnded_rck | RxAbort) + ShiftWillEnd <=#Tp 1'b0; + else + if(StartShiftWillEnd) + ShiftWillEnd <=#Tp 1'b1; +end + + + +// Receive byte counter +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxByteCnt <=#Tp 2'h0; + else + if(ShiftEnded_rck | RxAbort) + RxByteCnt <=#Tp 2'h0; + else + if(RxValid & RxStartFrm & RxReady) + case(RxPointerLSB_rst) // synopsys parallel_case + 2'h0 : RxByteCnt <=#Tp 2'h1; + 2'h1 : RxByteCnt <=#Tp 2'h2; + 2'h2 : RxByteCnt <=#Tp 2'h3; + 2'h3 : RxByteCnt <=#Tp 2'h0; + endcase + else + if(RxValid & RxEnableWindow & RxReady | LastByteIn) + RxByteCnt <=#Tp RxByteCnt + 1'b1; +end + + +// Indicates how many bytes are valid within the last word +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxValidBytes <=#Tp 2'h1; + else + if(RxValid & RxStartFrm) + case(RxPointerLSB_rst) // synopsys parallel_case + 2'h0 : RxValidBytes <=#Tp 2'h1; + 2'h1 : RxValidBytes <=#Tp 2'h2; + 2'h2 : RxValidBytes <=#Tp 2'h3; + 2'h3 : RxValidBytes <=#Tp 2'h0; + endcase + else + if(RxValid & ~LastByteIn & ~RxStartFrm & RxEnableWindow) + RxValidBytes <=#Tp RxValidBytes + 1'b1; +end + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxDataLatched1 <=#Tp 24'h0; + else + if(RxValid & RxReady & ~LastByteIn) + if(RxStartFrm) + begin + case(RxPointerLSB_rst) // synopsys parallel_case + 2'h0: RxDataLatched1[31:24] <=#Tp RxData; // Big Endian Byte Ordering + 2'h1: RxDataLatched1[23:16] <=#Tp RxData; + 2'h2: RxDataLatched1[15:8] <=#Tp RxData; + 2'h3: RxDataLatched1 <=#Tp RxDataLatched1; + endcase + end + else if (RxEnableWindow) + begin + case(RxByteCnt) // synopsys parallel_case + 2'h0: RxDataLatched1[31:24] <=#Tp RxData; // Big Endian Byte Ordering + 2'h1: RxDataLatched1[23:16] <=#Tp RxData; + 2'h2: RxDataLatched1[15:8] <=#Tp RxData; + 2'h3: RxDataLatched1 <=#Tp RxDataLatched1; + endcase + end +end + +wire SetWriteRxDataToFifo; + +// Assembling data that will be written to the rx_fifo +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxDataLatched2 <=#Tp 32'h0; + else + if(SetWriteRxDataToFifo & ~ShiftWillEnd) + RxDataLatched2 <=#Tp {RxDataLatched1[31:8], RxData}; // Big Endian Byte Ordering + else + if(SetWriteRxDataToFifo & ShiftWillEnd) + case(RxValidBytes) // synopsys parallel_case + 0 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], RxData}; // Big Endian Byte Ordering + 1 : RxDataLatched2 <=#Tp {RxDataLatched1[31:24], 24'h0}; + 2 : RxDataLatched2 <=#Tp {RxDataLatched1[31:16], 16'h0}; + 3 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], 8'h0}; + endcase +end + + +reg WriteRxDataToFifoSync1; +reg WriteRxDataToFifoSync2; +reg WriteRxDataToFifoSync3; + + +// Indicating start of the reception process +assign SetWriteRxDataToFifo = (RxValid & RxReady & ~RxStartFrm & RxEnableWindow & (&RxByteCnt)) | + (RxValid & RxReady & RxStartFrm & (&RxPointerLSB_rst)) | + (ShiftWillEnd & LastByteIn & (&RxByteCnt)); + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + WriteRxDataToFifo <=#Tp 1'b0; + else + if(SetWriteRxDataToFifo & ~RxAbort) + WriteRxDataToFifo <=#Tp 1'b1; + else + if(WriteRxDataToFifoSync2 | RxAbort) + WriteRxDataToFifo <=#Tp 1'b0; +end + + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + WriteRxDataToFifoSync1 <=#Tp 1'b0; + else + if(WriteRxDataToFifo) + WriteRxDataToFifoSync1 <=#Tp 1'b1; + else + WriteRxDataToFifoSync1 <=#Tp 1'b0; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + WriteRxDataToFifoSync2 <=#Tp 1'b0; + else + WriteRxDataToFifoSync2 <=#Tp WriteRxDataToFifoSync1; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + WriteRxDataToFifoSync3 <=#Tp 1'b0; + else + WriteRxDataToFifoSync3 <=#Tp WriteRxDataToFifoSync2; +end + +wire WriteRxDataToFifo_wb; +assign WriteRxDataToFifo_wb = WriteRxDataToFifoSync2 & ~WriteRxDataToFifoSync3; + + +reg LatchedRxStartFrm; +reg SyncRxStartFrm; +reg SyncRxStartFrm_q; +reg SyncRxStartFrm_q2; +wire RxFifoReset; + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LatchedRxStartFrm <=#Tp 0; + else + if(RxStartFrm & ~SyncRxStartFrm_q) + LatchedRxStartFrm <=#Tp 1; + else + if(SyncRxStartFrm_q) + LatchedRxStartFrm <=#Tp 0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + SyncRxStartFrm <=#Tp 0; + else + if(LatchedRxStartFrm) + SyncRxStartFrm <=#Tp 1; + else + SyncRxStartFrm <=#Tp 0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + SyncRxStartFrm_q <=#Tp 0; + else + SyncRxStartFrm_q <=#Tp SyncRxStartFrm; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + SyncRxStartFrm_q2 <=#Tp 0; + else + SyncRxStartFrm_q2 <=#Tp SyncRxStartFrm_q; +end + + +assign RxFifoReset = SyncRxStartFrm_q & ~SyncRxStartFrm_q2; + + +eth_fifo #(`ETH_RX_FIFO_DATA_WIDTH, `ETH_RX_FIFO_DEPTH, `ETH_RX_FIFO_CNT_WIDTH) +rx_fifo (.data_in(RxDataLatched2), .data_out(m_wb_dat_o), + .clk(WB_CLK_I), .reset(Reset), + .write(WriteRxDataToFifo_wb & ~RxBufferFull), .read(MasterWbRX & m_wb_ack_i), + .clear(RxFifoReset), .full(RxBufferFull), + .almost_full(), .almost_empty(RxBufferAlmostEmpty), + .empty(RxBufferEmpty), .cnt(rxfifo_cnt) + ); + +assign enough_data_in_rxfifo_for_burst = rxfifo_cnt>=`ETH_BURST_LENGTH; +assign enough_data_in_rxfifo_for_burst_plus1 = rxfifo_cnt>`ETH_BURST_LENGTH; +assign WriteRxDataToMemory = ~RxBufferEmpty; +assign rx_burst = rx_burst_en & WriteRxDataToMemory; + + +// Generation of the end-of-frame signal +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ShiftEnded_rck <=#Tp 1'b0; + else + if(~RxAbort & SetWriteRxDataToFifo & StartShiftWillEnd) + ShiftEnded_rck <=#Tp 1'b1; + else + if(RxAbort | ShiftEndedSync_c1 & ShiftEndedSync_c2) + ShiftEnded_rck <=#Tp 1'b0; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ShiftEndedSync1 <=#Tp 1'b0; + else + ShiftEndedSync1 <=#Tp ShiftEnded_rck; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ShiftEndedSync2 <=#Tp 1'b0; + else + ShiftEndedSync2 <=#Tp ShiftEndedSync1; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ShiftEndedSync3 <=#Tp 1'b0; + else + if(ShiftEndedSync1 & ~ShiftEndedSync2) + ShiftEndedSync3 <=#Tp 1'b1; + else + if(ShiftEnded) + ShiftEndedSync3 <=#Tp 1'b0; +end + +// Generation of the end-of-frame signal +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + ShiftEnded <=#Tp 1'b0; + else + if(ShiftEndedSync3 & MasterWbRX & m_wb_ack_i & RxBufferAlmostEmpty & ~ShiftEnded) + ShiftEnded <=#Tp 1'b1; + else + if(RxStatusWrite) + ShiftEnded <=#Tp 1'b0; +end + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ShiftEndedSync_c1 <=#Tp 1'b0; + else + ShiftEndedSync_c1 <=#Tp ShiftEndedSync2; +end + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + ShiftEndedSync_c2 <=#Tp 1'b0; + else + ShiftEndedSync_c2 <=#Tp ShiftEndedSync_c1; +end + +// Generation of the end-of-frame signal +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxEnableWindow <=#Tp 1'b0; + else + if(RxStartFrm) + RxEnableWindow <=#Tp 1'b1; + else + if(RxEndFrm | RxAbort) + RxEnableWindow <=#Tp 1'b0; +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxAbortSync1 <=#Tp 1'b0; + else + RxAbortSync1 <=#Tp RxAbortLatched; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxAbortSync2 <=#Tp 1'b0; + else + RxAbortSync2 <=#Tp RxAbortSync1; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxAbortSync3 <=#Tp 1'b0; + else + RxAbortSync3 <=#Tp RxAbortSync2; +end + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxAbortSync4 <=#Tp 1'b0; + else + RxAbortSync4 <=#Tp RxAbortSync3; +end + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxAbortSyncb1 <=#Tp 1'b0; + else + RxAbortSyncb1 <=#Tp RxAbortSync2; +end + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxAbortSyncb2 <=#Tp 1'b0; + else + RxAbortSyncb2 <=#Tp RxAbortSyncb1; +end + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxAbortLatched <=#Tp 1'b0; + else + if(RxAbortSyncb2) + RxAbortLatched <=#Tp 1'b0; + else + if(RxAbort) + RxAbortLatched <=#Tp 1'b1; +end + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + LatchedRxLength[15:0] <=#Tp 16'h0; + else + if(LoadRxStatus) + LatchedRxLength[15:0] <=#Tp RxLength[15:0]; +end + + +assign RxStatusIn = {ReceivedPauseFrm, AddressMiss, RxOverrun, InvalidSymbol, DribbleNibble, ReceivedPacketTooBig, ShortFrame, LatchedCrcError, RxLateCollision}; + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + RxStatusInLatched <=#Tp 'h0; + else + if(LoadRxStatus) + RxStatusInLatched <=#Tp RxStatusIn; +end + + +// Rx overrun +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxOverrun <=#Tp 1'b0; + else + if(RxStatusWrite) + RxOverrun <=#Tp 1'b0; + else + if(RxBufferFull & WriteRxDataToFifo_wb) + RxOverrun <=#Tp 1'b1; +end + + + +wire TxError; +assign TxError = TxUnderRun | RetryLimit | LateCollLatched | CarrierSenseLost; + +wire RxError; + +// ShortFrame (RxStatusInLatched[2]) can not set an error because short frames +// are aborted when signal r_RecSmall is set to 0 in MODER register. +// AddressMiss is identifying that a frame was received because of the promiscous +// mode and is not an error +assign RxError = (|RxStatusInLatched[6:3]) | (|RxStatusInLatched[1:0]); + + + +reg RxStatusWriteLatched; +reg RxStatusWriteLatched_sync1; +reg RxStatusWriteLatched_sync2; +reg RxStatusWriteLatched_syncb1; +reg RxStatusWriteLatched_syncb2; + + +// Latching and synchronizing RxStatusWrite signal. This signal is used for clearing the ReceivedPauseFrm signal +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxStatusWriteLatched <=#Tp 1'b0; + else + if(RxStatusWriteLatched_syncb2) + RxStatusWriteLatched <=#Tp 1'b0; + else + if(RxStatusWrite) + RxStatusWriteLatched <=#Tp 1'b1; +end + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + begin + RxStatusWriteLatched_sync1 <=#Tp 1'b0; + RxStatusWriteLatched_sync2 <=#Tp 1'b0; + end + else + begin + RxStatusWriteLatched_sync1 <=#Tp RxStatusWriteLatched; + RxStatusWriteLatched_sync2 <=#Tp RxStatusWriteLatched_sync1; + end +end + + +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + begin + RxStatusWriteLatched_syncb1 <=#Tp 1'b0; + RxStatusWriteLatched_syncb2 <=#Tp 1'b0; + end + else + begin + RxStatusWriteLatched_syncb1 <=#Tp RxStatusWriteLatched_sync2; + RxStatusWriteLatched_syncb2 <=#Tp RxStatusWriteLatched_syncb1; + end +end + + + +// Tx Done Interrupt +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxB_IRQ <=#Tp 1'b0; + else + if(TxStatusWrite & TxIRQEn) + TxB_IRQ <=#Tp ~TxError; + else + TxB_IRQ <=#Tp 1'b0; +end + + +// Tx Error Interrupt +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + TxE_IRQ <=#Tp 1'b0; + else + if(TxStatusWrite & TxIRQEn) + TxE_IRQ <=#Tp TxError; + else + TxE_IRQ <=#Tp 1'b0; +end + + +// Rx Done Interrupt +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxB_IRQ <=#Tp 1'b0; + else + if(RxStatusWrite & RxIRQEn & ReceivedPacketGood & (~ReceivedPauseFrm | ReceivedPauseFrm & r_PassAll & (~r_RxFlow))) + RxB_IRQ <=#Tp (~RxError); + else + RxB_IRQ <=#Tp 1'b0; +end + + +// Rx Error Interrupt +always @ (posedge WB_CLK_I or posedge Reset) +begin + if(Reset) + RxE_IRQ <=#Tp 1'b0; + else + if(RxStatusWrite & RxIRQEn & (~ReceivedPauseFrm | ReceivedPauseFrm & r_PassAll & (~r_RxFlow))) + RxE_IRQ <=#Tp RxError; + else + RxE_IRQ <=#Tp 1'b0; +end + + +// Busy Interrupt + +reg Busy_IRQ_rck; +reg Busy_IRQ_sync1; +reg Busy_IRQ_sync2; +reg Busy_IRQ_sync3; +reg Busy_IRQ_syncb1; +reg Busy_IRQ_syncb2; + + +always @ (posedge MRxClk or posedge Reset) +begin + if(Reset) + Busy_IRQ_rck <=#Tp 1'b0; + else + if(RxValid & RxStartFrm & ~RxReady) + Busy_IRQ_rck <=#Tp 1'b1; + else + if(Busy_IRQ_syncb2) + Busy_IRQ_rck <=#Tp 1'b0; +end + +always @ (posedge WB_CLK_I) +begin + Busy_IRQ_sync1 <=#Tp Busy_IRQ_rck; + Busy_IRQ_sync2 <=#Tp Busy_IRQ_sync1; + Busy_IRQ_sync3 <=#Tp Busy_IRQ_sync2; +end + +always @ (posedge MRxClk) +begin + Busy_IRQ_syncb1 <=#Tp Busy_IRQ_sync2; + Busy_IRQ_syncb2 <=#Tp Busy_IRQ_syncb1; +end + +assign Busy_IRQ = Busy_IRQ_sync2 & ~Busy_IRQ_sync3; + + + + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v b/openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v new file mode 100644 index 000000000..49516f072 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v @@ -0,0 +1,53 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// timescale.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: timescale.v,v $ +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 11:36:31 mohor +// Log file added. +// +// +// + +`timescale 1ns / 1ns diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v b/openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v new file mode 100644 index 000000000..374357ce0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v @@ -0,0 +1,50 @@ +module xilinx_dist_ram_16x32 +( + data_out, + we, + data_in, + read_address, + write_address, + wclk +); + output [31:0] data_out; + input we, wclk; + input [31:0] data_in; + input [3:0] write_address, read_address; + + wire [3:0] waddr = write_address ; + wire [3:0] raddr = read_address ; + + RAM16X1D ram00 (.DPO(data_out[0]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[0]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram01 (.DPO(data_out[1]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[1]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram02 (.DPO(data_out[2]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[2]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram03 (.DPO(data_out[3]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[3]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram04 (.DPO(data_out[4]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[4]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram05 (.DPO(data_out[5]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[5]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram06 (.DPO(data_out[6]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[6]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram07 (.DPO(data_out[7]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[7]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram08 (.DPO(data_out[8]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[8]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram09 (.DPO(data_out[9]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[9]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram10 (.DPO(data_out[10]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[10]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram11 (.DPO(data_out[11]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[11]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram12 (.DPO(data_out[12]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[12]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram13 (.DPO(data_out[13]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[13]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram14 (.DPO(data_out[14]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[14]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram15 (.DPO(data_out[15]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[15]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram16 (.DPO(data_out[16]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[16]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram17 (.DPO(data_out[17]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[17]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram18 (.DPO(data_out[18]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[18]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram19 (.DPO(data_out[19]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[19]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram20 (.DPO(data_out[20]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[20]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram21 (.DPO(data_out[21]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[21]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram22 (.DPO(data_out[22]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[22]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram23 (.DPO(data_out[23]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[23]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram24 (.DPO(data_out[24]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[24]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram25 (.DPO(data_out[25]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[25]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram26 (.DPO(data_out[26]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[26]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram27 (.DPO(data_out[27]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[27]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram28 (.DPO(data_out[28]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[28]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram29 (.DPO(data_out[29]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[29]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram30 (.DPO(data_out[30]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[30]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); + RAM16X1D ram31 (.DPO(data_out[31]), .SPO(), .A0(waddr[0]), .A1(waddr[1]), .A2(waddr[2]), .A3(waddr[3]), .D(data_in[31]), .DPRA0(raddr[0]), .DPRA1(raddr[1]), .DPRA2(raddr[2]), .DPRA3(raddr[3]), .WCLK(wclk), .WE(we)); +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/except.v b/openfpga_flow/benchmarks/iwls2005/fpu/except.v new file mode 100644 index 000000000..007099fe1 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/fpu/except.v @@ -0,0 +1,153 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// EXCEPT //// +//// Floating Point Exception/Special Numbers Unit //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +`timescale 1ns / 100ps + + +module except( clk, opa, opb, inf, ind, qnan, snan, opa_nan, opb_nan, + opa_00, opb_00, opa_inf, opb_inf, opa_dn, opb_dn); +input clk; +input [31:0] opa, opb; +output inf, ind, qnan, snan, opa_nan, opb_nan; +output opa_00, opb_00; +output opa_inf, opb_inf; +output opa_dn; +output opb_dn; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +wire [7:0] expa, expb; // alias to opX exponent +wire [22:0] fracta, fractb; // alias to opX fraction +reg expa_ff, infa_f_r, qnan_r_a, snan_r_a; +reg expb_ff, infb_f_r, qnan_r_b, snan_r_b; +reg inf, ind, qnan, snan; // Output registers +reg opa_nan, opb_nan; +reg expa_00, expb_00, fracta_00, fractb_00; +reg opa_00, opb_00; +reg opa_inf, opb_inf; +reg opa_dn, opb_dn; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign expa = opa[30:23]; +assign expb = opb[30:23]; +assign fracta = opa[22:0]; +assign fractb = opb[22:0]; + +//////////////////////////////////////////////////////////////////////// +// +// Determine if any of the input operators is a INF or NAN or any other special number +// + +always @(posedge clk) + expa_ff <= #1 &expa; + +always @(posedge clk) + expb_ff <= #1 &expb; + +always @(posedge clk) + infa_f_r <= #1 !(|fracta); + +always @(posedge clk) + infb_f_r <= #1 !(|fractb); + +always @(posedge clk) + qnan_r_a <= #1 fracta[22]; + +always @(posedge clk) + snan_r_a <= #1 !fracta[22] & |fracta[21:0]; + +always @(posedge clk) + qnan_r_b <= #1 fractb[22]; + +always @(posedge clk) + snan_r_b <= #1 !fractb[22] & |fractb[21:0]; + +always @(posedge clk) + ind <= #1 (expa_ff & infa_f_r) & (expb_ff & infb_f_r); + +always @(posedge clk) + inf <= #1 (expa_ff & infa_f_r) | (expb_ff & infb_f_r); + +always @(posedge clk) + qnan <= #1 (expa_ff & qnan_r_a) | (expb_ff & qnan_r_b); + +always @(posedge clk) + snan <= #1 (expa_ff & snan_r_a) | (expb_ff & snan_r_b); + +always @(posedge clk) + opa_nan <= #1 &expa & (|fracta[22:0]); + +always @(posedge clk) + opb_nan <= #1 &expb & (|fractb[22:0]); + +always @(posedge clk) + opa_inf <= #1 (expa_ff & infa_f_r); + +always @(posedge clk) + opb_inf <= #1 (expb_ff & infb_f_r); + +always @(posedge clk) + expa_00 <= #1 !(|expa); + +always @(posedge clk) + expb_00 <= #1 !(|expb); + +always @(posedge clk) + fracta_00 <= #1 !(|fracta); + +always @(posedge clk) + fractb_00 <= #1 !(|fractb); + +always @(posedge clk) + opa_00 <= #1 expa_00 & fracta_00; + +always @(posedge clk) + opb_00 <= #1 expb_00 & fractb_00; + +always @(posedge clk) + opa_dn <= #1 expa_00; + +always @(posedge clk) + opb_dn <= #1 expb_00; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/fpu.v b/openfpga_flow/benchmarks/iwls2005/fpu/fpu.v new file mode 100644 index 000000000..165a1d246 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/fpu/fpu.v @@ -0,0 +1,560 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// FPU //// +//// Floating Point Unit (Single precision) //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + +/* + +FPU Operations (fpu_op): +======================== + +0 = add +1 = sub +2 = mul +3 = div +4 = +5 = +6 = +7 = + +Rounding Modes (rmode): +======================= + +0 = round_nearest_even +1 = round_to_zero +2 = round_up +3 = round_down + +*/ + + +module fpu( clk, rmode, fpu_op, opa, opb, out, inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero); +input clk; +input [1:0] rmode; +input [2:0] fpu_op; +input [31:0] opa, opb; +output [31:0] out; +output inf, snan, qnan; +output ine; +output overflow, underflow; +output zero; +output div_by_zero; + +parameter INF = 31'h7f800000, + QNAN = 31'h7fc00001, + SNAN = 31'h7f800001; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires +// +reg zero; +reg [31:0] opa_r, opb_r; // Input operand registers +reg [31:0] out; // Output register +reg div_by_zero; // Divide by zero output register +wire signa, signb; // alias to opX sign +wire sign_fasu; // sign output +wire [26:0] fracta, fractb; // Fraction Outputs from EQU block +wire [7:0] exp_fasu; // Exponent output from EQU block +reg [7:0] exp_r; // Exponent output (registerd) +wire [26:0] fract_out_d; // fraction output +wire co; // carry output +reg [27:0] fract_out_q; // fraction output (registerd) +wire [30:0] out_d; // Intermediate final result output +wire overflow_d, underflow_d;// Overflow/Underflow Indicators +reg overflow, underflow; // Output registers for Overflow & Underflow +reg inf, snan, qnan; // Output Registers for INF, SNAN and QNAN +reg ine; // Output Registers for INE +reg [1:0] rmode_r1, rmode_r2, // Pipeline registers for rounding mode + rmode_r3; +reg [2:0] fpu_op_r1, fpu_op_r2, // Pipeline registers for fp opration + fpu_op_r3; +wire mul_inf, div_inf; +wire mul_00, div_00; + +//////////////////////////////////////////////////////////////////////// +// +// Input Registers +// + +always @(posedge clk) + opa_r <= #1 opa; + +always @(posedge clk) + opb_r <= #1 opb; + +always @(posedge clk) + rmode_r1 <= #1 rmode; + +always @(posedge clk) + rmode_r2 <= #1 rmode_r1; + +always @(posedge clk) + rmode_r3 <= #1 rmode_r2; + +always @(posedge clk) + fpu_op_r1 <= #1 fpu_op; + +always @(posedge clk) + fpu_op_r2 <= #1 fpu_op_r1; + +always @(posedge clk) + fpu_op_r3 <= #1 fpu_op_r2; + +//////////////////////////////////////////////////////////////////////// +// +// Exceptions block +// +wire inf_d, ind_d, qnan_d, snan_d, opa_nan, opb_nan; +wire opa_00, opb_00; +wire opa_inf, opb_inf; +wire opa_dn, opb_dn; + +except u0( .clk(clk), + .opa(opa_r), .opb(opb_r), + .inf(inf_d), .ind(ind_d), + .qnan(qnan_d), .snan(snan_d), + .opa_nan(opa_nan), .opb_nan(opb_nan), + .opa_00(opa_00), .opb_00(opb_00), + .opa_inf(opa_inf), .opb_inf(opb_inf), + .opa_dn(opa_dn), .opb_dn(opb_dn) + ); + +//////////////////////////////////////////////////////////////////////// +// +// Pre-Normalize block +// - Adjusts the numbers to equal exponents and sorts them +// - determine result sign +// - determine actual operation to perform (add or sub) +// + +wire nan_sign_d, result_zero_sign_d; +reg sign_fasu_r; +wire [7:0] exp_mul; +wire sign_mul; +reg sign_mul_r; +wire [23:0] fracta_mul, fractb_mul; +wire inf_mul; +reg inf_mul_r; +wire [1:0] exp_ovf; +reg [1:0] exp_ovf_r; +wire sign_exe; +reg sign_exe_r; +wire [2:0] underflow_fmul_d; + + +pre_norm u1(.clk(clk), // System Clock + .rmode(rmode_r2), // Roundin Mode + .add(!fpu_op_r1[0]), // Add/Sub Input + .opa(opa_r), .opb(opb_r), // Registered OP Inputs + .opa_nan(opa_nan), // OpA is a NAN indicator + .opb_nan(opb_nan), // OpB is a NAN indicator + .fracta_out(fracta), // Equalized and sorted fraction + .fractb_out(fractb), // outputs (Registered) + .exp_dn_out(exp_fasu), // Selected exponent output (registered); + .sign(sign_fasu), // Encoded output Sign (registered) + .nan_sign(nan_sign_d), // Output Sign for NANs (registered) + .result_zero_sign(result_zero_sign_d), // Output Sign for zero result (registered) + .fasu_op(fasu_op) // Actual fasu operation output (registered) + ); + +always @(posedge clk) + sign_fasu_r <= #1 sign_fasu; + +pre_norm_fmul u2( + .clk(clk), + .fpu_op(fpu_op_r1), + .opa(opa_r), .opb(opb_r), + .fracta(fracta_mul), + .fractb(fractb_mul), + .exp_out(exp_mul), // FMUL exponent output (registered) + .sign(sign_mul), // FMUL sign output (registered) + .sign_exe(sign_exe), // FMUL exception sign output (registered) + .inf(inf_mul), // FMUL inf output (registered) + .exp_ovf(exp_ovf), // FMUL exponnent overflow output (registered) + .underflow(underflow_fmul_d) + ); + + +always @(posedge clk) + sign_mul_r <= #1 sign_mul; + +always @(posedge clk) + sign_exe_r <= #1 sign_exe; + +always @(posedge clk) + inf_mul_r <= #1 inf_mul; + +always @(posedge clk) + exp_ovf_r <= #1 exp_ovf; + + +//////////////////////////////////////////////////////////////////////// +// +// Add/Sub +// + +add_sub27 u3( + .add(fasu_op), // Add/Sub + .opa(fracta), // Fraction A input + .opb(fractb), // Fraction B Input + .sum(fract_out_d), // SUM output + .co(co_d) ); // Carry Output + +always @(posedge clk) + fract_out_q <= #1 {co_d, fract_out_d}; + +//////////////////////////////////////////////////////////////////////// +// +// Mul +// +wire [47:0] prod; + +mul_r2 u5(.clk(clk), .opa(fracta_mul), .opb(fractb_mul), .prod(prod)); + +//////////////////////////////////////////////////////////////////////// +// +// Divide +// +wire [49:0] quo; +wire [49:0] fdiv_opa; +wire [49:0] remainder; +wire remainder_00; +reg [4:0] div_opa_ldz_d, div_opa_ldz_r1, div_opa_ldz_r2; + +always @(fracta_mul) + casex(fracta_mul[22:0]) + 23'b1??????????????????????: div_opa_ldz_d = 1; + 23'b01?????????????????????: div_opa_ldz_d = 2; + 23'b001????????????????????: div_opa_ldz_d = 3; + 23'b0001???????????????????: div_opa_ldz_d = 4; + 23'b00001??????????????????: div_opa_ldz_d = 5; + 23'b000001?????????????????: div_opa_ldz_d = 6; + 23'b0000001????????????????: div_opa_ldz_d = 7; + 23'b00000001???????????????: div_opa_ldz_d = 8; + 23'b000000001??????????????: div_opa_ldz_d = 9; + 23'b0000000001?????????????: div_opa_ldz_d = 10; + 23'b00000000001????????????: div_opa_ldz_d = 11; + 23'b000000000001???????????: div_opa_ldz_d = 12; + 23'b0000000000001??????????: div_opa_ldz_d = 13; + 23'b00000000000001?????????: div_opa_ldz_d = 14; + 23'b000000000000001????????: div_opa_ldz_d = 15; + 23'b0000000000000001???????: div_opa_ldz_d = 16; + 23'b00000000000000001??????: div_opa_ldz_d = 17; + 23'b000000000000000001?????: div_opa_ldz_d = 18; + 23'b0000000000000000001????: div_opa_ldz_d = 19; + 23'b00000000000000000001???: div_opa_ldz_d = 20; + 23'b000000000000000000001??: div_opa_ldz_d = 21; + 23'b0000000000000000000001?: div_opa_ldz_d = 22; + 23'b0000000000000000000000?: div_opa_ldz_d = 23; + endcase + +assign fdiv_opa = !(|opa_r[30:23]) ? {(fracta_mul<f2i_emax)) | (opas & (exp_inf2i_emax)) | (opas & (exp_in8'h16); + +assign f2i_shft = exp_in-8'h7d; + +// Select shifting direction +assign left_right = op_div ? lr_div : op_mul ? lr_mul : 1; + +assign lr_div = (op_dn & !exp_ovf[1] & exp_ovf[0]) ? 1 : + (op_dn & exp_ovf[1]) ? 0 : + (op_dn & div_shft1_co) ? 0 : + (op_dn & exp_out_00) ? 1 : + (!op_dn & exp_out_00 & !exp_ovf[1]) ? 1 : + exp_ovf[1] ? 0 : + 1; +assign lr_mul = (shft_co | (!exp_ovf[1] & exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00) )) ? 1 : + ( exp_ovf[1] | exp_in_00 ) ? 0 : + 1; + +// Select Left and Right shift value +assign fasu_shift = (dn | exp_out_00) ? (exp_in_00 ? 8'h2 : exp_in_pl1[7:0]) : {2'h0, fi_ldz}; +assign shift_right = op_div ? shftr_div : shftr_mul; + +assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz}; + +assign shift_left = op_div ? shftl_div : op_mul ? shftl_mul : (op_f2i | op_i2f) ? conv_shft : fasu_shift; + +assign shftl_mul = (shft_co | + (!exp_ovf[1] & exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00))) ? exp_in_pl1[7:0] : {2'h0, fi_ldz}; + +assign shftl_div = ( op_dn & exp_out_00 & !(!exp_ovf[1] & exp_ovf[0])) ? div_shft1[7:0] : + (!op_dn & exp_out_00 & !exp_ovf[1]) ? exp_in[7:0] : + {2'h0, fi_ldz}; +assign shftr_div = (op_dn & exp_ovf[1]) ? div_shft3 : + (op_dn & div_shft1_co) ? div_shft4 : + div_shft2; +// Do the actual shifting +assign fract_in_shftr = (|shift_right[7:6]) ? 0 : fract_in>>shift_right[5:0]; +assign fract_in_shftl = (|shift_left[7:6] | (f2i_zero & op_f2i)) ? 0 : fract_in<f2i_emax) ? 0 : opas) : + ((exp_inf2i_emax) ? 1 : opas); + +assign exp_i2f = fract_in_00 ? (opas ? 8'h9e : 0) : (8'h9e-fi_ldz); +assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<9'hfe) )) ? div_exp2 : + (opa_dn | (exp_in_00 & !exp_ovf[1]) ) ? 0 : + exp_out1_mi1; + +assign div_inf = opb_dn & !opa_dn & (div_exp1[7:0] < 8'h7f); + +// --------------------------------------------------------------------- +// Round + +// Extract rounding (GRS) bits +assign grs_sel_div = op_div & (exp_ovf[1] | div_dn | exp_out1_co | exp_out_00); + +assign g = grs_sel_div ? fract_out[0] : fract_out[0]; +assign r = grs_sel_div ? (fract_trunc[24] & !div_nr) : fract_trunc[24]; +assign s = grs_sel_div ? |fract_trunc[24:0] : (|fract_trunc[23:0] | (fract_trunc[24] & op_div)); + +// Round to nearest even +assign round = (g & r) | (r & s) ; +assign {exp_rnd_adj0, fract_out_rnd0} = round ? fract_out_pl1 : {1'b0, fract_out}; +assign exp_out_rnd0 = exp_rnd_adj0 ? exp_out_pl1 : exp_out; +assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i; + +// round to zero +assign fract_out_rnd1 = (exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out; +assign exp_fix_div = (fi_ldz>22) ? exp_fix_diva : exp_fix_divb; +assign exp_out_rnd1 = (g & r & s & exp_in_ff) ? (op_div ? exp_fix_div : exp_next_mi[7:0]) : + (exp_out_ff & !op_f2i) ? exp_in : exp_out; +assign ovf1 = exp_out_ff & !dn; + +// round to +inf (UP) and -inf (DOWN) +assign r_sign = sign; + +assign round2a = !exp_out_fe | !fract_out_7fffff | (exp_out_fe & fract_out_7fffff); +assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] | (exp_out[7] & round2a)); + +assign round2_fmul = !r_sign & + ( + (exp_ovf[1] & !fract_in_00 & + ( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div)) + ) | + ( + (r | s | (!rem_00 & op_div)) & ( + (!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div | + ( exp_ovf[1] & !exp_ovf[0] & exp_out1_co) + ) + ) + ); + +assign round2_f2i = rmode_10 & (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) | (|fract_trunc)); +assign round2 = (op_mul | op_div) ? round2_fmul : op_f2i ? round2_f2i : round2_fasu; + +assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 : {1'b0, fract_out}; +assign exp_out_rnd2a = exp_rnd_adj2a ? ((exp_ovf[1] & op_mul) ? exp_out_mi1 : exp_out_pl1) : exp_out; + +assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out_rnd2a; +assign exp_out_rnd2 = (r_sign & exp_out_ff & !op_f2i) ? 8'hfe : exp_out_rnd2a; + + +// Choose rounding mode +always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2) + case(rmode) // synopsys full_case parallel_case + 0: exp_out_rnd = exp_out_rnd0; + 1: exp_out_rnd = exp_out_rnd1; + 2,3: exp_out_rnd = exp_out_rnd2; + endcase + +always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2) + case(rmode) // synopsys full_case parallel_case + 0: fract_out_rnd = fract_out_rnd0; + 1: fract_out_rnd = fract_out_rnd1; + 2,3: fract_out_rnd = fract_out_rnd2; + endcase + +// --------------------------------------------------------------------- +// Final Output Mux +// Fix Output for denormalized and special numbers +wire max_num, inf_out; + +assign max_num = ( !rmode_00 & (op_mul | op_div ) & ( + ( exp_ovf[1] & exp_ovf[0]) | + (!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<24) & (exp_out!=8'hfe) ) + ) + ) | + + ( op_div & ( + ( rmode_01 & ( div_inf | + (exp_out_ff & !exp_ovf[1] ) | + (exp_ovf[1] & exp_ovf[0] ) + ) + ) | + + ( rmode[1] & !exp_ovf[1] & ( + ( exp_ovf[0] & exp_in_ff & r_sign & fract_in[47] + ) | + + ( r_sign & ( + (fract_in[47] & div_inf) | + (exp_in[7] & !exp_out_rnd[7] & !exp_in_80 & exp_out!=8'h7f ) | + (exp_in[7] & exp_out_rnd[7] & r_sign & exp_out_ff & op_dn & + div_exp1>9'h0fe ) + ) + ) | + + ( exp_in_00 & r_sign & ( + div_inf | + (r_sign & exp_out_ff & fi_ldz_2<24) + ) + ) + ) + ) + ) + ); + + +assign inf_out = (rmode[1] & (op_mul | op_div) & !r_sign & ( (exp_in_ff & !op_div) | + (exp_ovf[1] & exp_ovf[0] & (exp_in_00 | exp_in[7]) ) + ) + ) | (div_inf & op_div & ( + rmode_00 | + (rmode[1] & !exp_in_ff & !exp_ovf[1] & !exp_ovf[0] & !r_sign ) | + (rmode[1] & !exp_ovf[1] & exp_ovf[0] & exp_in_00 & !r_sign) + ) + ) | (op_div & rmode[1] & exp_in_ff & op_dn & !r_sign & (fi_ldz_2 < 24) & (exp_out_rnd!=8'hfe) ); + +assign fract_out_final = (inf_out | ovf0 | output_zero ) ? 23'h0 : + (max_num | (f2i_max & op_f2i) ) ? 23'h7fffff : + fract_out_rnd; + +assign exp_out_final = ((op_div & exp_ovf[1] & !exp_ovf[0]) | output_zero ) ? 8'h00 : + ((op_div & exp_ovf[1] & exp_ovf[0] & rmode_00) | inf_out | (f2i_max & op_f2i) ) ? 8'hff : + max_num ? 8'hfe : + exp_out_rnd; + + +// --------------------------------------------------------------------- +// Pack Result + +assign out = {exp_out_final, fract_out_final}; + +// --------------------------------------------------------------------- +// Exceptions +wire underflow_fmul; +wire overflow_fdiv; +wire undeflow_div; + +wire z = shft_co | ( exp_ovf[1] | exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00)); + +assign underflow_fmul = ( (|fract_trunc) & z & !exp_in_ff ) | + (fract_out_00 & !fract_in_00 & exp_ovf[1]); + +assign undeflow_div = !(exp_ovf[1] & exp_ovf[0] & rmode_00) & !inf_out & !max_num & exp_out_final!=8'hff & ( + + ((|fract_trunc) & !opb_dn & ( + ( op_dn & !exp_ovf[1] & exp_ovf[0]) | + ( op_dn & exp_ovf[1]) | + ( op_dn & div_shft1_co) | + exp_out_00 | + exp_ovf[1] + ) + + ) | + + ( exp_ovf[1] & !exp_ovf[0] & ( + ( op_dn & exp_in>8'h16 & fi_ldz<23) | + ( op_dn & exp_in<23 & fi_ldz<23 & !rem_00) | + ( !op_dn & (exp_in[7]==exp_div[7]) & !rem_00) | + ( !op_dn & exp_in_00 & (exp_div[7:1]==7'h7f) ) | + ( !op_dn & exp_in<8'h7f & exp_in>8'h20 ) + ) + ) | + + (!exp_ovf[1] & !exp_ovf[0] & ( + ( op_dn & fi_ldz<23 & exp_out_00) | + ( exp_in_00 & !rem_00) | + ( !op_dn & ldz_all<23 & exp_in==1 & exp_out_00 & !rem_00) + ) + ) + + ); + +assign underflow = op_div ? undeflow_div : op_mul ? underflow_fmul : (!fract_in[47] & exp_out1_co) & !dn; + +assign overflow_fdiv = inf_out | + (!rmode_00 & max_num) | + (exp_in[7] & op_dn & exp_out_ff) | + (exp_ovf[0] & (exp_ovf[1] | exp_out_ff) ); + +assign overflow = op_div ? overflow_fdiv : (ovf0 | ovf1); + +wire f2i_ine; + +assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) | + (|fract_trunc) | + (f2i_zero & (exp_in<8'h80) & opas & !fract_in_00) | + (f2i_max & rmode_11 & (exp_in<8'h80)); + + + +assign ine = op_f2i ? f2i_ine : + op_i2f ? (|fract_trunc) : + ((r & !dn) | (s & !dn) | max_num | (op_div & !rem_00)); + +// --------------------------------------------------------------------- +// Debugging Stuff + +// synopsys translate_off + +wire [26:0] fracta_del, fractb_del; +wire [2:0] grs_del; +wire dn_del; +wire [7:0] exp_in_del; +wire [7:0] exp_out_del; +wire [22:0] fract_out_del; +wire [47:0] fract_in_del; +wire overflow_del; +wire [1:0] exp_ovf_del; +wire [22:0] fract_out_x_del, fract_out_rnd2a_del; +wire [24:0] trunc_xx_del; +wire exp_rnd_adj2a_del; +wire [22:0] fract_dn_del; +wire [4:0] div_opa_ldz_del; +wire [23:0] fracta_div_del; +wire [23:0] fractb_div_del; +wire div_inf_del; +wire [7:0] fi_ldz_2_del; +wire inf_out_del, max_out_del; +wire [5:0] fi_ldz_del; +wire rx_del; +wire ez_del; +wire lr; +wire [7:0] shr, shl, exp_div_del; + +delay2 #26 ud000(clk, test.u0.fracta, fracta_del); +delay2 #26 ud001(clk, test.u0.fractb, fractb_del); +delay1 #2 ud002(clk, {g,r,s}, grs_del); +delay1 #0 ud004(clk, dn, dn_del); +delay1 #7 ud005(clk, exp_in, exp_in_del); +delay1 #7 ud007(clk, exp_out_rnd, exp_out_del); +delay1 #47 ud009(clk, fract_in, fract_in_del); +delay1 #0 ud010(clk, overflow, overflow_del); +delay1 #1 ud011(clk, exp_ovf, exp_ovf_del); +delay1 #22 ud014(clk, fract_out, fract_out_x_del); +delay1 #24 ud015(clk, fract_trunc, trunc_xx_del); +delay1 #0 ud017(clk, exp_rnd_adj2a, exp_rnd_adj2a_del); +delay1 #4 ud019(clk, div_opa_ldz, div_opa_ldz_del); +delay3 #23 ud020(clk, test.u0.fdiv_opa[49:26], fracta_div_del); +delay3 #23 ud021(clk, test.u0.fractb_mul, fractb_div_del); +delay1 #0 ud023(clk, div_inf, div_inf_del); +delay1 #7 ud024(clk, fi_ldz_2, fi_ldz_2_del); +delay1 #0 ud025(clk, inf_out, inf_out_del); +delay1 #0 ud026(clk, max_num, max_num_del); +delay1 #5 ud027(clk, fi_ldz, fi_ldz_del); +delay1 #0 ud028(clk, rem_00, rx_del); + +delay1 #0 ud029(clk, left_right, lr); +delay1 #7 ud030(clk, shift_right, shr); +delay1 #7 ud031(clk, shift_left, shl); +delay1 #22 ud032(clk, fract_out_rnd2a, fract_out_rnd2a_del); + +delay1 #7 ud033(clk, exp_div, exp_div_del); + +always @(test.error_event) + begin + + $display("\n----------------------------------------------"); + + $display("ERROR: GRS: %b exp_ovf: %b dn: %h exp_in: %h exp_out: %h, exp_rnd_adj2a: %b", + grs_del, exp_ovf_del, dn_del, exp_in_del, exp_out_del, exp_rnd_adj2a_del); + + $display(" div_opa: %b, div_opb: %b, rem_00: %b, exp_div: %h", + fracta_div_del, fractb_div_del, rx_del, exp_div_del); + + $display(" lr: %b, shl: %h, shr: %h", + lr, shl, shr); + + + $display(" overflow: %b, fract_in=%b fa:%h fb:%h", + overflow_del, fract_in_del, fracta_del, fractb_del); + + $display(" div_opa_ldz: %h, div_inf: %b, inf_out: %b, max_num: %b, fi_ldz: %h, fi_ldz_2: %h", + div_opa_ldz_del, div_inf_del, inf_out_del, max_num_del, fi_ldz_del, fi_ldz_2_del); + + $display(" fract_out_x: %b, fract_out_rnd2a_del: %h, fract_trunc: %b\n", + fract_out_x_del, fract_out_rnd2a_del, trunc_xx_del); + end + + +// synopsys translate_on + +endmodule + +// synopsys translate_off + +module delay1(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out; + +always @(posedge clk) + out <= #1 in; + +endmodule + + +module delay2(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out, r1; + +always @(posedge clk) + r1 <= #1 in; + +always @(posedge clk) + out <= #1 r1; + +endmodule + +module delay3(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out, r1, r2; + +always @(posedge clk) + r1 <= #1 in; + +always @(posedge clk) + r2 <= #1 r1; + +always @(posedge clk) + out <= #1 r2; + +endmodule + +// synopsys translate_on \ No newline at end of file diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v b/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v new file mode 100644 index 000000000..c54c71fa2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v @@ -0,0 +1,270 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Pre Normalize //// +//// Pre Normalization Unit for Add/Sub Operations //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + + +module pre_norm(clk, rmode, add, opa, opb, opa_nan, opb_nan, fracta_out, + fractb_out, exp_dn_out, sign, nan_sign, result_zero_sign, + fasu_op); +input clk; +input [1:0] rmode; +input add; +input [31:0] opa, opb; +input opa_nan, opb_nan; +output [26:0] fracta_out, fractb_out; +output [7:0] exp_dn_out; +output sign; +output nan_sign, result_zero_sign; +output fasu_op; // Operation Output + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +wire signa, signb; // alias to opX sign +wire [7:0] expa, expb; // alias to opX exponent +wire [22:0] fracta, fractb; // alias to opX fraction +wire expa_lt_expb; // expa is larger than expb indicator +wire fractb_lt_fracta; // fractb is larger than fracta indicator +reg [7:0] exp_dn_out; // de normalized exponent output +wire [7:0] exp_small, exp_large; +wire [7:0] exp_diff; // Numeric difference of the two exponents +wire [22:0] adj_op; // Fraction adjustment: input +wire [26:0] adj_op_tmp; +wire [26:0] adj_op_out; // Fraction adjustment: output +wire [26:0] fracta_n, fractb_n; // Fraction selection after normalizing +wire [26:0] fracta_s, fractb_s; // Fraction Sorting out +reg [26:0] fracta_out, fractb_out; // Fraction Output +reg sign, sign_d; // Sign Output +reg add_d; // operation (add/sub) +reg fasu_op; // operation (add/sub) register +wire expa_dn, expb_dn; +reg sticky; +reg result_zero_sign; +reg add_r, signa_r, signb_r; +wire [4:0] exp_diff_sft; +wire exp_lt_27; +wire op_dn; +wire [26:0] adj_op_out_sft; +reg fracta_lt_fractb, fracta_eq_fractb; +wire nan_sign1; +reg nan_sign; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign signa = opa[31]; +assign signb = opb[31]; +assign expa = opa[30:23]; +assign expb = opb[30:23]; +assign fracta = opa[22:0]; +assign fractb = opb[22:0]; + +//////////////////////////////////////////////////////////////////////// +// +// Pre-Normalize exponents (and fractions) +// + +assign expa_lt_expb = expa > expb; // expa is larger than expb + +// --------------------------------------------------------------------- +// Normalize + +assign expa_dn = !(|expa); // opa denormalized +assign expb_dn = !(|expb); // opb denormalized + +// --------------------------------------------------------------------- +// Calculate the difference between the smaller and larger exponent + +wire [7:0] exp_diff1, exp_diff1a, exp_diff2; + +assign exp_small = expa_lt_expb ? expb : expa; +assign exp_large = expa_lt_expb ? expa : expb; +assign exp_diff1 = exp_large - exp_small; +assign exp_diff1a = exp_diff1-1; +assign exp_diff2 = (expa_dn | expb_dn) ? exp_diff1a : exp_diff1; +assign exp_diff = (expa_dn & expb_dn) ? 8'h0 : exp_diff2; + +always @(posedge clk) // If numbers are equal we should return zero + exp_dn_out <= #1 (!add_d & expa==expb & fracta==fractb) ? 8'h0 : exp_large; + +// --------------------------------------------------------------------- +// Adjust the smaller fraction + + +assign op_dn = expa_lt_expb ? expb_dn : expa_dn; +assign adj_op = expa_lt_expb ? fractb : fracta; +assign adj_op_tmp = { ~op_dn, adj_op, 3'b0 }; // recover hidden bit (op_dn) + +// adj_op_out is 27 bits wide, so can only be shifted 27 bits to the right +assign exp_lt_27 = exp_diff > 8'd27; +assign exp_diff_sft = exp_lt_27 ? 5'd27 : exp_diff[4:0]; +assign adj_op_out_sft = adj_op_tmp >> exp_diff_sft; +assign adj_op_out = {adj_op_out_sft[26:1], adj_op_out_sft[0] | sticky }; + +// --------------------------------------------------------------------- +// Get truncated portion (sticky bit) + +always @(exp_diff_sft or adj_op_tmp) + case(exp_diff_sft) // synopsys full_case parallel_case + 00: sticky = 1'h0; + 01: sticky = adj_op_tmp[0]; + 02: sticky = |adj_op_tmp[01:0]; + 03: sticky = |adj_op_tmp[02:0]; + 04: sticky = |adj_op_tmp[03:0]; + 05: sticky = |adj_op_tmp[04:0]; + 06: sticky = |adj_op_tmp[05:0]; + 07: sticky = |adj_op_tmp[06:0]; + 08: sticky = |adj_op_tmp[07:0]; + 09: sticky = |adj_op_tmp[08:0]; + 10: sticky = |adj_op_tmp[09:0]; + 11: sticky = |adj_op_tmp[10:0]; + 12: sticky = |adj_op_tmp[11:0]; + 13: sticky = |adj_op_tmp[12:0]; + 14: sticky = |adj_op_tmp[13:0]; + 15: sticky = |adj_op_tmp[14:0]; + 16: sticky = |adj_op_tmp[15:0]; + 17: sticky = |adj_op_tmp[16:0]; + 18: sticky = |adj_op_tmp[17:0]; + 19: sticky = |adj_op_tmp[18:0]; + 20: sticky = |adj_op_tmp[19:0]; + 21: sticky = |adj_op_tmp[20:0]; + 22: sticky = |adj_op_tmp[21:0]; + 23: sticky = |adj_op_tmp[22:0]; + 24: sticky = |adj_op_tmp[23:0]; + 25: sticky = |adj_op_tmp[24:0]; + 26: sticky = |adj_op_tmp[25:0]; + 27: sticky = |adj_op_tmp[26:0]; + endcase + +// --------------------------------------------------------------------- +// Select operands for add/sub (recover hidden bit) + +assign fracta_n = expa_lt_expb ? {~expa_dn, fracta, 3'b0} : adj_op_out; +assign fractb_n = expa_lt_expb ? adj_op_out : {~expb_dn, fractb, 3'b0}; + +// --------------------------------------------------------------------- +// Sort operands (for sub only) + +assign fractb_lt_fracta = fractb_n > fracta_n; // fractb is larger than fracta +assign fracta_s = fractb_lt_fracta ? fractb_n : fracta_n; +assign fractb_s = fractb_lt_fracta ? fracta_n : fractb_n; + +always @(posedge clk) + fracta_out <= #1 fracta_s; + +always @(posedge clk) + fractb_out <= #1 fractb_s; + +// --------------------------------------------------------------------- +// Determine sign for the output + +// sign: 0=Positive Number; 1=Negative Number +always @(signa or signb or add or fractb_lt_fracta) + case({signa, signb, add}) // synopsys full_case parallel_case + + // Add + 3'b0_0_1: sign_d = 0; + 3'b0_1_1: sign_d = fractb_lt_fracta; + 3'b1_0_1: sign_d = !fractb_lt_fracta; + 3'b1_1_1: sign_d = 1; + + // Sub + 3'b0_0_0: sign_d = fractb_lt_fracta; + 3'b0_1_0: sign_d = 0; + 3'b1_0_0: sign_d = 1; + 3'b1_1_0: sign_d = !fractb_lt_fracta; + endcase + +always @(posedge clk) + sign <= #1 sign_d; + +// Fix sign for ZERO result +always @(posedge clk) + signa_r <= #1 signa; + +always @(posedge clk) + signb_r <= #1 signb; + +always @(posedge clk) + add_r <= #1 add; + +always @(posedge clk) + result_zero_sign <= #1 ( add_r & signa_r & signb_r) | + (!add_r & signa_r & !signb_r) | + ( add_r & (signa_r | signb_r) & (rmode==3)) | + (!add_r & (signa_r == signb_r) & (rmode==3)); + +// Fix sign for NAN result +always @(posedge clk) + fracta_lt_fractb <= #1 fracta < fractb; + +always @(posedge clk) + fracta_eq_fractb <= #1 fracta == fractb; + +assign nan_sign1 = fracta_eq_fractb ? (signa_r & signb_r) : fracta_lt_fractb ? signb_r : signa_r; + +always @(posedge clk) + nan_sign <= #1 (opa_nan & opb_nan) ? nan_sign1 : opb_nan ? signb_r : signa_r; + +//////////////////////////////////////////////////////////////////////// +// +// Decode Add/Sub operation +// + +// add: 1=Add; 0=Subtract +always @(signa or signb or add) + case({signa, signb, add}) // synopsys full_case parallel_case + + // Add + 3'b0_0_1: add_d = 1; + 3'b0_1_1: add_d = 0; + 3'b1_0_1: add_d = 0; + 3'b1_1_1: add_d = 1; + + // Sub + 3'b0_0_0: add_d = 0; + 3'b0_1_0: add_d = 1; + 3'b1_0_0: add_d = 1; + 3'b1_1_0: add_d = 0; + endcase + +always @(posedge clk) + fasu_op <= #1 add_d; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v b/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v new file mode 100644 index 000000000..26ddfeb75 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v @@ -0,0 +1,150 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Pre Normalize //// +//// Floating Point Pre Normalization Unit for FMUL //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + +module pre_norm_fmul(clk, fpu_op, opa, opb, fracta, fractb, exp_out, sign, + sign_exe, inf, exp_ovf, underflow); +input clk; +input [2:0] fpu_op; +input [31:0] opa, opb; +output [23:0] fracta, fractb; +output [7:0] exp_out; +output sign, sign_exe; +output inf; +output [1:0] exp_ovf; +output [2:0] underflow; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +reg [7:0] exp_out; +wire signa, signb; +reg sign, sign_d; +reg sign_exe; +reg inf; +wire [1:0] exp_ovf_d; +reg [1:0] exp_ovf; +wire [7:0] expa, expb; +wire [7:0] exp_tmp1, exp_tmp2; +wire co1, co2; +wire expa_dn, expb_dn; +wire [7:0] exp_out_a; +wire opa_00, opb_00, fracta_00, fractb_00; +wire [7:0] exp_tmp3, exp_tmp4, exp_tmp5; +wire [2:0] underflow_d; +reg [2:0] underflow; +wire op_div = (fpu_op == 3'b011); +wire [7:0] exp_out_mul, exp_out_div; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign signa = opa[31]; +assign signb = opb[31]; +assign expa = opa[30:23]; +assign expb = opb[30:23]; + +//////////////////////////////////////////////////////////////////////// +// +// Calculate Exponenet +// + +assign expa_dn = !(|expa); +assign expb_dn = !(|expb); +assign opa_00 = !(|opa[30:0]); +assign opb_00 = !(|opb[30:0]); +assign fracta_00 = !(|opa[22:0]); +assign fractb_00 = !(|opb[22:0]); + +assign fracta = {!expa_dn,opa[22:0]}; // Recover hidden bit +assign fractb = {!expb_dn,opb[22:0]}; // Recover hidden bit + +assign {co1,exp_tmp1} = op_div ? (expa - expb) : (expa + expb); +assign {co2,exp_tmp2} = op_div ? ({co1,exp_tmp1} + 8'h7f) : ({co1,exp_tmp1} - 8'h7f); + +assign exp_tmp3 = exp_tmp2 + 1; +assign exp_tmp4 = 8'h7f - exp_tmp1; +assign exp_tmp5 = op_div ? (exp_tmp4+1) : (exp_tmp4-1); + + +always@(posedge clk) + exp_out <= #1 op_div ? exp_out_div : exp_out_mul; + +assign exp_out_div = (expa_dn | expb_dn) ? (co2 ? exp_tmp5 : exp_tmp3 ) : co2 ? exp_tmp4 : exp_tmp2; +assign exp_out_mul = exp_ovf_d[1] ? exp_out_a : (expa_dn | expb_dn) ? exp_tmp3 : exp_tmp2; +assign exp_out_a = (expa_dn | expb_dn) ? exp_tmp5 : exp_tmp4; +assign exp_ovf_d[0] = op_div ? (expa[7] & !expb[7]) : (co2 & expa[7] & expb[7]); +assign exp_ovf_d[1] = op_div ? co2 : ((!expa[7] & !expb[7] & exp_tmp2[7]) | co2); + +always @(posedge clk) + exp_ovf <= #1 exp_ovf_d; + +assign underflow_d[0] = (exp_tmp1 < 8'h7f) & !co1 & !(opa_00 | opb_00 | expa_dn | expb_dn); +assign underflow_d[1] = ((expa[7] | expb[7]) & !opa_00 & !opb_00) | + (expa_dn & !fracta_00) | (expb_dn & !fractb_00); +assign underflow_d[2] = !opa_00 & !opb_00 & (exp_tmp1 == 8'h7f); + +always @(posedge clk) + underflow <= #1 underflow_d; + +always @(posedge clk) + inf <= #1 op_div ? (expb_dn & !expa[7]) : ({co1,exp_tmp1} > 9'h17e) ; + + +//////////////////////////////////////////////////////////////////////// +// +// Determine sign for the output +// + +// sign: 0=Posetive Number; 1=Negative Number +always @(signa or signb) + case({signa, signb}) // synopsys full_case parallel_case + 2'b0_0: sign_d = 0; + 2'b0_1: sign_d = 1; + 2'b1_0: sign_d = 1; + 2'b1_1: sign_d = 0; + endcase + +always @(posedge clk) + sign <= #1 sign_d; + +always @(posedge clk) + sign_exe <= #1 signa & signb; + +endmodule \ No newline at end of file diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/primitives.v b/openfpga_flow/benchmarks/iwls2005/fpu/primitives.v new file mode 100644 index 000000000..2e7f050e5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/fpu/primitives.v @@ -0,0 +1,103 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Primitives //// +//// FPU Primitives //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +`timescale 1ns / 100ps + + +//////////////////////////////////////////////////////////////////////// +// +// Add/Sub +// + +module add_sub27(add, opa, opb, sum, co); +input add; +input [26:0] opa, opb; +output [26:0] sum; +output co; + + + +assign {co, sum} = add ? (opa + opb) : (opa - opb); + +endmodule + +//////////////////////////////////////////////////////////////////////// +// +// Multiply +// + +module mul_r2(clk, opa, opb, prod); +input clk; +input [23:0] opa, opb; +output [47:0] prod; + +reg [47:0] prod1, prod; + +always @(posedge clk) + prod1 <= #1 opa * opb; + +always @(posedge clk) + prod <= #1 prod1; + +endmodule + +//////////////////////////////////////////////////////////////////////// +// +// Divide +// + +module div_r2(clk, opa, opb, quo, rem); +input clk; +input [49:0] opa; +input [23:0] opb; +output [49:0] quo, rem; + +reg [49:0] quo, rem, quo1, remainder; + +always @(posedge clk) + quo1 <= #1 opa / opb; + +always @(posedge clk) + quo <= #1 quo1; + +always @(posedge clk) + remainder <= #1 opa % opb; + +always @(posedge clk) + rem <= #1 remainder; + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v new file mode 100644 index 000000000..17b2c8b1f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v @@ -0,0 +1,535 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master bit-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_bit_ctrl.v,v 1.11 2004/05/07 11:02:26 rherveille Exp $ +// +// $Date: 2004/05/07 11:02:26 $ +// $Revision: 1.11 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_bit_ctrl.v,v $ +// Revision 1.11 2004/05/07 11:02:26 rherveille +// Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +// +// Revision 1.10 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.9 2003/03/10 14:26:37 rherveille +// Fixed cmd_ack generation item (no bug). +// +// Revision 1.8 2003/02/05 00:06:10 rherveille +// Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +// +// Revision 1.7 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.6 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.5 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.4 2002/10/30 18:10:07 rherveille +// Fixed some reported minor start/stop generation timing issuess. +// +// Revision 1.3 2002/06/15 07:37:03 rherveille +// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +// +// Revision 1.2 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// +///////////////////////////////////// +// Bit controller section +///////////////////////////////////// +// +// Translate simple commands into SCL/SDA transitions +// Each command has 5 states, A/B/C/D/idle +// +// start: SCL ~~~~~~~~~~\____ +// SDA ~~~~~~~~\______ +// x | A | B | C | D | i +// +// repstart SCL ____/~~~~\___ +// SDA __/~~~\______ +// x | A | B | C | D | i +// +// stop SCL ____/~~~~~~~~ +// SDA ==\____/~~~~~ +// x | A | B | C | D | i +// +//- write SCL ____/~~~~\____ +// SDA ==X=========X= +// x | A | B | C | D | i +// +//- read SCL ____/~~~~\____ +// SDA XXXX=====XXXX +// x | A | B | C | D | i +// + +// Timing: Normal mode Fast mode +/////////////////////////////////////////////////////////////////////// +// Fscl 100KHz 400KHz +// Th_scl 4.0us 0.6us High period of SCL +// Tl_scl 4.7us 1.3us Low period of SCL +// Tsu:sta 4.7us 0.6us setup time for a repeated start condition +// Tsu:sto 4.0us 0.6us setup time for a stop conditon +// Tbuf 4.7us 1.3us Bus free time between a stop and start condition +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_bit_ctrl( + clk, rst, nReset, + clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout, + scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen + ); + + // + // inputs & outputs + // + input clk; + input rst; + input nReset; + input ena; // core enable signal + + input [15:0] clk_cnt; // clock prescale value + + input [3:0] cmd; + output cmd_ack; // command complete acknowledge + reg cmd_ack; + output busy; // i2c bus busy + reg busy; + output al; // i2c bus arbitration lost + reg al; + + input din; + output dout; + reg dout; + + // I2C lines + input scl_i; // i2c clock line input + output scl_o; // i2c clock line output + output scl_oen; // i2c clock line output enable (active low) + reg scl_oen; + input sda_i; // i2c data line input + output sda_o; // i2c data line output + output sda_oen; // i2c data line output enable (active low) + reg sda_oen; + + + // + // variable declarations + // + + reg sSCL, sSDA; // synchronized SCL and SDA inputs + reg dscl_oen; // delayed scl_oen + reg sda_chk; // check SDA output (Multi-master arbitration) + reg clk_en; // clock generation signals + wire slave_wait; +// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation) + reg [15:0] cnt; // clock divider counter (synthesis) + + // state machine variable + reg [16:0] c_state; // synopsys enum_state + + // + // module body + // + + // whenever the slave is not ready it can delay the cycle by pulling SCL low + // delay scl_oen + always @(posedge clk) + dscl_oen <= #1 scl_oen; + + assign slave_wait = dscl_oen && !sSCL; + + + // generate clk enable signal + always @(posedge clk or negedge nReset) + if(~nReset) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if (rst) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if ( ~|cnt || ~ena) + if (~slave_wait) + begin + cnt <= #1 clk_cnt; + clk_en <= #1 1'b1; + end + else + begin + cnt <= #1 cnt; + clk_en <= #1 1'b0; + end + else + begin + cnt <= #1 cnt - 16'h1; + clk_en <= #1 1'b0; + end + + + // generate bus status controller + reg dSCL, dSDA; + reg sta_condition; + reg sto_condition; + + // synchronize SCL and SDA inputs + // reduce metastability risc + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else if (rst) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else + begin + sSCL <= #1 scl_i; + sSDA <= #1 sda_i; + + dSCL <= #1 sSCL; + dSDA <= #1 sSDA; + end + + // detect start condition => detect falling edge on SDA while SCL is high + // detect stop condition => detect rising edge on SDA while SCL is high + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else if (rst) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else + begin + sta_condition <= #1 ~sSDA & dSDA & sSCL; + sto_condition <= #1 sSDA & ~dSDA & sSCL; + end + + // generate i2c bus busy signal + always @(posedge clk or negedge nReset) + if(!nReset) + busy <= #1 1'b0; + else if (rst) + busy <= #1 1'b0; + else + busy <= #1 (sta_condition | busy) & ~sto_condition; + + // generate arbitration lost signal + // aribitration lost when: + // 1) master drives SDA high, but the i2c bus is low + // 2) stop detected while not requested + reg cmd_stop; + always @(posedge clk or negedge nReset) + if (~nReset) + cmd_stop <= #1 1'b0; + else if (rst) + cmd_stop <= #1 1'b0; + else if (clk_en) + cmd_stop <= #1 cmd == `I2C_CMD_STOP; + + always @(posedge clk or negedge nReset) + if (~nReset) + al <= #1 1'b0; + else if (rst) + al <= #1 1'b0; + else + al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop); + + + // generate dout signal (store SDA on rising edge of SCL) + always @(posedge clk) + if(sSCL & ~dSCL) + dout <= #1 sSDA; + + // generate statemachine + + // nxt_state decoder + parameter [16:0] idle = 17'b0_0000_0000_0000_0000; + parameter [16:0] start_a = 17'b0_0000_0000_0000_0001; + parameter [16:0] start_b = 17'b0_0000_0000_0000_0010; + parameter [16:0] start_c = 17'b0_0000_0000_0000_0100; + parameter [16:0] start_d = 17'b0_0000_0000_0000_1000; + parameter [16:0] start_e = 17'b0_0000_0000_0001_0000; + parameter [16:0] stop_a = 17'b0_0000_0000_0010_0000; + parameter [16:0] stop_b = 17'b0_0000_0000_0100_0000; + parameter [16:0] stop_c = 17'b0_0000_0000_1000_0000; + parameter [16:0] stop_d = 17'b0_0000_0001_0000_0000; + parameter [16:0] rd_a = 17'b0_0000_0010_0000_0000; + parameter [16:0] rd_b = 17'b0_0000_0100_0000_0000; + parameter [16:0] rd_c = 17'b0_0000_1000_0000_0000; + parameter [16:0] rd_d = 17'b0_0001_0000_0000_0000; + parameter [16:0] wr_a = 17'b0_0010_0000_0000_0000; + parameter [16:0] wr_b = 17'b0_0100_0000_0000_0000; + parameter [16:0] wr_c = 17'b0_1000_0000_0000_0000; + parameter [16:0] wr_d = 17'b1_0000_0000_0000_0000; + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else if (rst | al) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else + begin + cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle + + if (clk_en) + case (c_state) // synopsys full_case parallel_case + // idle state + idle: + begin + case (cmd) // synopsys full_case parallel_case + `I2C_CMD_START: + c_state <= #1 start_a; + + `I2C_CMD_STOP: + c_state <= #1 stop_a; + + `I2C_CMD_WRITE: + c_state <= #1 wr_a; + + `I2C_CMD_READ: + c_state <= #1 rd_a; + + default: + c_state <= #1 idle; + endcase + + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 sda_oen; // keep SDA in same state + sda_chk <= #1 1'b0; // don't check SDA output + end + + // start + start_a: + begin + c_state <= #1 start_b; + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_b: + begin + c_state <= #1 start_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_c: + begin + c_state <= #1 start_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_d: + begin + c_state <= #1 start_e; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_e: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + // stop + stop_a: + begin + c_state <= #1 stop_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_b: + begin + c_state <= #1 stop_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_c: + begin + c_state <= #1 stop_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + // read + rd_a: + begin + c_state <= #1 rd_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b1; // tri-state SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_b: + begin + c_state <= #1 rd_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_c: + begin + c_state <= #1 rd_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + // write + wr_a: + begin + c_state <= #1 wr_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 din; // set SDA + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + wr_b: + begin + c_state <= #1 wr_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 din; // keep SDA + sda_chk <= #1 1'b1; // check SDA output + end + + wr_c: + begin + c_state <= #1 wr_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 din; + sda_chk <= #1 1'b1; // check SDA output + end + + wr_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 din; + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + endcase + end + + + // assign scl and sda output (always gnd) + assign scl_o = 1'b0; + assign sda_o = 1'b0; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v new file mode 100644 index 000000000..d091d1e36 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v @@ -0,0 +1,344 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master byte-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_byte_ctrl.v,v 1.7 2004/02/18 11:40:46 rherveille Exp $ +// +// $Date: 2004/02/18 11:40:46 $ +// $Revision: 1.7 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_byte_ctrl.v,v $ +// Revision 1.7 2004/02/18 11:40:46 rherveille +// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command. +// +// Revision 1.6 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.5 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.4 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_byte_ctrl ( + clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din, + cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); + + // + // inputs & outputs + // + input clk; // master clock + input rst; // synchronous active high reset + input nReset; // asynchronous active low reset + input ena; // core enable signal + + input [15:0] clk_cnt; // 4x SCL + + // control inputs + input start; + input stop; + input read; + input write; + input ack_in; + input [7:0] din; + + // status outputs + output cmd_ack; + reg cmd_ack; + output ack_out; + reg ack_out; + output i2c_busy; + output i2c_al; + output [7:0] dout; + + // I2C signals + input scl_i; + output scl_o; + output scl_oen; + input sda_i; + output sda_o; + output sda_oen; + + + // + // Variable declarations + // + + // statemachine + parameter [4:0] ST_IDLE = 5'b0_0000; + parameter [4:0] ST_START = 5'b0_0001; + parameter [4:0] ST_READ = 5'b0_0010; + parameter [4:0] ST_WRITE = 5'b0_0100; + parameter [4:0] ST_ACK = 5'b0_1000; + parameter [4:0] ST_STOP = 5'b1_0000; + + // signals for bit_controller + reg [3:0] core_cmd; + reg core_txd; + wire core_ack, core_rxd; + + // signals for shift register + reg [7:0] sr; //8bit shift register + reg shift, ld; + + // signals for state machine + wire go; + reg [2:0] dcnt; + wire cnt_done; + + // + // Module body + // + + // hookup bit_controller + i2c_master_bit_ctrl bit_controller ( + .clk ( clk ), + .rst ( rst ), + .nReset ( nReset ), + .ena ( ena ), + .clk_cnt ( clk_cnt ), + .cmd ( core_cmd ), + .cmd_ack ( core_ack ), + .busy ( i2c_busy ), + .al ( i2c_al ), + .din ( core_txd ), + .dout ( core_rxd ), + .scl_i ( scl_i ), + .scl_o ( scl_o ), + .scl_oen ( scl_oen ), + .sda_i ( sda_i ), + .sda_o ( sda_o ), + .sda_oen ( sda_oen ) + ); + + // generate go-signal + assign go = (read | write | stop) & ~cmd_ack; + + // assign dout output to shift-register + assign dout = sr; + + // generate shift register + always @(posedge clk or negedge nReset) + if (!nReset) + sr <= #1 8'h0; + else if (rst) + sr <= #1 8'h0; + else if (ld) + sr <= #1 din; + else if (shift) + sr <= #1 {sr[6:0], core_rxd}; + + // generate counter + always @(posedge clk or negedge nReset) + if (!nReset) + dcnt <= #1 3'h0; + else if (rst) + dcnt <= #1 3'h0; + else if (ld) + dcnt <= #1 3'h7; + else if (shift) + dcnt <= #1 dcnt - 3'h1; + + assign cnt_done = ~(|dcnt); + + // + // state machine + // + reg [4:0] c_state; // synopsis enum_state + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else if (rst | i2c_al) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else + begin + // initially reset all signals + core_txd <= #1 sr[7]; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + + case (c_state) // synopsys full_case parallel_case + ST_IDLE: + if (go) + begin + if (start) + begin + c_state <= #1 ST_START; + core_cmd <= #1 `I2C_CMD_START; + end + else if (read) + begin + c_state <= #1 ST_READ; + core_cmd <= #1 `I2C_CMD_READ; + end + else if (write) + begin + c_state <= #1 ST_WRITE; + core_cmd <= #1 `I2C_CMD_WRITE; + end + else // stop + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + + ld <= #1 1'b1; + end + + ST_START: + if (core_ack) + begin + if (read) + begin + c_state <= #1 ST_READ; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; + core_cmd <= #1 `I2C_CMD_WRITE; + end + + ld <= #1 1'b1; + end + + ST_WRITE: + if (core_ack) + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; // stay in same state + core_cmd <= #1 `I2C_CMD_WRITE; // write next bit + shift <= #1 1'b1; + end + + ST_READ: + if (core_ack) + begin + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_WRITE; + end + else + begin + c_state <= #1 ST_READ; // stay in same state + core_cmd <= #1 `I2C_CMD_READ; // read next bit + end + + shift <= #1 1'b1; + core_txd <= #1 ack_in; + end + + ST_ACK: + if (core_ack) + begin + if (stop) + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + else + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + // assign ack_out output to bit_controller_rxd (contains last received bit) + ack_out <= #1 core_rxd; + + core_txd <= #1 1'b1; + end + else + core_txd <= #1 ack_in; + + ST_STOP: + if (core_ack) + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + endcase + end +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v new file mode 100644 index 000000000..ee3b694fa --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master controller defines //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_defines.v,v 1.3 2001/11/05 11:59:25 rherveille Exp $ +// +// $Date: 2001/11/05 11:59:25 $ +// $Revision: 1.3 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_defines.v,v $ +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + + +// I2C registers wishbone addresses + +// bitcontroller states +`define I2C_CMD_NOP 4'b0000 +`define I2C_CMD_START 4'b0001 +`define I2C_CMD_STOP 4'b0010 +`define I2C_CMD_WRITE 4'b0100 +`define I2C_CMD_READ 4'b1000 diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v new file mode 100644 index 000000000..30689bd70 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v @@ -0,0 +1,301 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE revB.2 compliant I2C Master controller Top-level //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_top.v,v 1.11 2005/02/27 09:26:24 rherveille Exp $ +// +// $Date: 2005/02/27 09:26:24 $ +// $Revision: 1.11 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_top.v,v $ +// Revision 1.11 2005/02/27 09:26:24 rherveille +// Fixed register overwrite issue. +// Removed full_case pragma, replaced it by a default statement. +// +// Revision 1.10 2003/09/01 10:34:38 rherveille +// Fix a blocking vs. non-blocking error in the wb_dat output mux. +// +// Revision 1.9 2003/01/09 16:44:45 rherveille +// Fixed a bug in the Command Register declaration. +// +// Revision 1.8 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.7 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.6 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.5 2001/11/10 10:52:55 rherveille +// Changed PRER reset value from 0x0000 to 0xffff, conform specs. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_top( + wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, + wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, + scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); + + // parameters + parameter ARST_LVL = 1'b0; // asynchronous reset level + + // + // inputs & outputs + // + + // wishbone signals + input wb_clk_i; // master clock input + input wb_rst_i; // synchronous active high reset + input arst_i; // asynchronous reset + input [2:0] wb_adr_i; // lower address bits + input [7:0] wb_dat_i; // databus input + output [7:0] wb_dat_o; // databus output + input wb_we_i; // write enable input + input wb_stb_i; // stobe/core select signal + input wb_cyc_i; // valid bus cycle input + output wb_ack_o; // bus cycle acknowledge output + output wb_inta_o; // interrupt request signal output + + reg [7:0] wb_dat_o; + reg wb_ack_o; + reg wb_inta_o; + + // I2C signals + // i2c clock line + input scl_pad_i; // SCL-line input + output scl_pad_o; // SCL-line output (always 1'b0) + output scl_padoen_o; // SCL-line output enable (active low) + + // i2c data line + input sda_pad_i; // SDA-line input + output sda_pad_o; // SDA-line output (always 1'b0) + output sda_padoen_o; // SDA-line output enable (active low) + + + // + // variable declarations + // + + // registers + reg [15:0] prer; // clock prescale register + reg [ 7:0] ctr; // control register + reg [ 7:0] txr; // transmit register + wire [ 7:0] rxr; // receive register + reg [ 7:0] cr; // command register + wire [ 7:0] sr; // status register + + // done signal: command completed, clear command register + wire done; + + // core enable signal + wire core_en; + wire ien; + + // status register signals + wire irxack; + reg rxack; // received aknowledge from slave + reg tip; // transfer in progress + reg irq_flag; // interrupt pending flag + wire i2c_busy; // bus busy (start signal detected) + wire i2c_al; // i2c bus arbitration lost + reg al; // status register arbitration lost bit + + // + // module body + // + + // generate internal reset + wire rst_i = arst_i ^ ARST_LVL; + + // generate wishbone signals + wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; + + // generate acknowledge output signal + always @(posedge wb_clk_i) + wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored + + // assign DAT_O + always @(posedge wb_clk_i) + begin + case (wb_adr_i) // synopsis parallel_case + 3'b000: wb_dat_o <= #1 prer[ 7:0]; + 3'b001: wb_dat_o <= #1 prer[15:8]; + 3'b010: wb_dat_o <= #1 ctr; + 3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr) + 3'b100: wb_dat_o <= #1 sr; // write is command register (cr) + 3'b101: wb_dat_o <= #1 txr; + 3'b110: wb_dat_o <= #1 cr; + 3'b111: wb_dat_o <= #1 0; // reserved + endcase + end + + // generate registers + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else if (wb_rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else + if (wb_wacc) + case (wb_adr_i) // synopsis parallel_case + 3'b000 : prer [ 7:0] <= #1 wb_dat_i; + 3'b001 : prer [15:8] <= #1 wb_dat_i; + 3'b010 : ctr <= #1 wb_dat_i; + 3'b011 : txr <= #1 wb_dat_i; + default: ; + endcase + + // generate command register (special case) + always @(posedge wb_clk_i or negedge rst_i) + if (~rst_i) + cr <= #1 8'h0; + else if (wb_rst_i) + cr <= #1 8'h0; + else if (wb_wacc) + begin + if (core_en & (wb_adr_i == 3'b100) ) + cr <= #1 wb_dat_i; + end + else + begin + if (done | i2c_al) + cr[7:4] <= #1 4'h0; // clear command bits when done + // or when aribitration lost + cr[2:1] <= #1 2'b0; // reserved bits + cr[0] <= #1 2'b0; // clear IRQ_ACK bit + end + + + // decode command register + wire sta = cr[7]; + wire sto = cr[6]; + wire rd = cr[5]; + wire wr = cr[4]; + wire ack = cr[3]; + wire iack = cr[0]; + + // decode control register + assign core_en = ctr[7]; + assign ien = ctr[6]; + + // hookup byte controller block + i2c_master_byte_ctrl byte_controller ( + .clk ( wb_clk_i ), + .rst ( wb_rst_i ), + .nReset ( rst_i ), + .ena ( core_en ), + .clk_cnt ( prer ), + .start ( sta ), + .stop ( sto ), + .read ( rd ), + .write ( wr ), + .ack_in ( ack ), + .din ( txr ), + .cmd_ack ( done ), + .ack_out ( irxack ), + .dout ( rxr ), + .i2c_busy ( i2c_busy ), + .i2c_al ( i2c_al ), + .scl_i ( scl_pad_i ), + .scl_o ( scl_pad_o ), + .scl_oen ( scl_padoen_o ), + .sda_i ( sda_pad_i ), + .sda_o ( sda_pad_o ), + .sda_oen ( sda_padoen_o ) + ); + + // status register block + interrupt request signal + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else if (wb_rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else + begin + al <= #1 i2c_al | (al & ~sta); + rxack <= #1 irxack; + tip <= #1 (rd | wr); + irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated + end + + // generate interrupt request signals + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + wb_inta_o <= #1 1'b0; + else if (wb_rst_i) + wb_inta_o <= #1 1'b0; + else + wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) + + // assign status register bits + assign sr[7] = rxack; + assign sr[6] = i2c_busy; + assign sr[5] = al; + assign sr[4:2] = 3'h0; // reserved + assign sr[1] = tip; + assign sr[0] = irq_flag; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/timescale.v b/openfpga_flow/benchmarks/iwls2005/i2c/timescale.v new file mode 100644 index 000000000..60d4ecbd1 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/i2c/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v new file mode 100644 index 000000000..0408fa86f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v @@ -0,0 +1,290 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Address Select Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_adr_sel.v,v 1.4 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_adr_sel.v,v $ +// Revision 1.4 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.3 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.2 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.1.1.1 2001/05/13 09:39:40 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_adr_sel(clk, csc, tms, wb_ack_o, wb_stb_i, wb_addr_i, wb_we_i, + wb_write_go, wr_hold, cas_, + mc_addr, row_adr, bank_adr, rfr_ack, + cs_le, cmd_a10, row_sel, lmr_sel, next_adr, wr_cycle, + page_size); + +input clk; +input [31:0] csc; +input [31:0] tms; +input wb_ack_o, wb_stb_i; +input [31:0] wb_addr_i; +input wb_we_i; +input wb_write_go; +input wr_hold; +input cas_; +output [23:0] mc_addr; +output [12:0] row_adr; +output [1:0] bank_adr; +input rfr_ack; +input cs_le; +input cmd_a10; +input row_sel; +input lmr_sel; +input next_adr; +input wr_cycle; +output [10:0] page_size; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg [23:0] mc_addr_d; +reg [23:0] acs_addr; +wire [23:0] acs_addr_pl1; +reg [23:0] sram_addr; +wire [14:0] sdram_adr; +reg [12:0] row_adr; +reg [9:0] col_adr; +reg [1:0] bank_adr; +reg [10:0] page_size; + +wire [2:0] mem_type; +wire [1:0] bus_width; +wire [1:0] mem_size; +wire bas; + +// Aliases +assign mem_type = csc[3:1]; +assign bus_width = csc[5:4]; +assign mem_size = csc[7:6]; +assign bas = csc[9]; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(mem_type or wr_hold or sdram_adr or acs_addr or sram_addr or wb_addr_i) + if(mem_type == `MC_MEM_TYPE_SDRAM) mc_addr_d = {9'h0, sdram_adr}; + else + if(mem_type == `MC_MEM_TYPE_ACS) mc_addr_d = acs_addr; + else + if((mem_type == `MC_MEM_TYPE_SRAM) & wr_hold) mc_addr_d = sram_addr; + else mc_addr_d = wb_addr_i[25:2]; + +assign mc_addr = rfr_ack ? {mc_addr_d[23:11], 1'b1, mc_addr_d[9:0]} : mc_addr_d; + +//////////////////////////////////////////////////////////////////// +// +// Async Devices Address Latch & Counter +// + +mc_incn_r #(24) u0( .clk( clk ), + .inc_in( acs_addr ), + .inc_out( acs_addr_pl1 ) ); + +always @(posedge clk) + if(wb_stb_i) sram_addr <= #1 wb_addr_i[25:2]; + +always @(posedge clk) + if(cs_le | wb_we_i) + case(bus_width) // synopsys full_case parallel_case + `MC_BW_8: acs_addr <= #1 wb_addr_i[23:0]; + `MC_BW_16: acs_addr <= #1 wb_addr_i[24:1]; + `MC_BW_32: acs_addr <= #1 wb_addr_i[25:2]; + endcase + else + if(next_adr) acs_addr <= #1 acs_addr_pl1; + +//////////////////////////////////////////////////////////////////// +// +// SDRAM Address Mux +// + +assign sdram_adr[12:0] = (lmr_sel & !cas_) ? tms[12:0] : + row_sel ? row_adr : + {2'h0, cmd_a10, col_adr}; + +assign sdram_adr[14:13] = bank_adr; + +always @(posedge clk) + if(wr_cycle ? wb_ack_o : wb_stb_i) + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: col_adr <= #1 {1'h0, wb_addr_i[10:2]}; + {`MC_BW_8, `MC_MEM_SIZE_128}: col_adr <= #1 wb_addr_i[11:2]; + {`MC_BW_8, `MC_MEM_SIZE_256}: col_adr <= #1 wb_addr_i[11:2]; + + {`MC_BW_16, `MC_MEM_SIZE_64}: col_adr <= #1 {2'h0, wb_addr_i[09:2]}; + {`MC_BW_16, `MC_MEM_SIZE_128}: col_adr <= #1 {1'h0, wb_addr_i[10:2]}; + {`MC_BW_16, `MC_MEM_SIZE_256}: col_adr <= #1 {1'h0, wb_addr_i[10:2]}; + + {`MC_BW_32, `MC_MEM_SIZE_64}: col_adr <= #1 {2'h0, wb_addr_i[09:2]}; + {`MC_BW_32, `MC_MEM_SIZE_128}: col_adr <= #1 {2'h0, wb_addr_i[09:2]}; + {`MC_BW_32, `MC_MEM_SIZE_256}: col_adr <= #1 {2'h0, wb_addr_i[09:2]}; + endcase + +always @(posedge clk) + if(cs_le) + begin + if(!bas) + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: row_adr <= #1 {1'h0, wb_addr_i[24:13]}; + {`MC_BW_8, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[25:14]}; + {`MC_BW_8, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[26:14]; + + {`MC_BW_16, `MC_MEM_SIZE_64}: row_adr <= #1 {1'h0, wb_addr_i[23:12]}; + {`MC_BW_16, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[24:13]}; + {`MC_BW_16, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[25:13]; + + {`MC_BW_32, `MC_MEM_SIZE_64}: row_adr <= #1 {2'h0, wb_addr_i[22:12]}; + {`MC_BW_32, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[23:12]}; + {`MC_BW_32, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[24:12]; + endcase + else + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: row_adr <= #1 {1'h0, wb_addr_i[22:11]}; + {`MC_BW_8, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[23:12]}; + {`MC_BW_8, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[24:12]; + + {`MC_BW_16, `MC_MEM_SIZE_64}: row_adr <= #1 {1'h0, wb_addr_i[21:10]}; + {`MC_BW_16, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[22:11]}; + {`MC_BW_16, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[23:11]; + + {`MC_BW_32, `MC_MEM_SIZE_64}: row_adr <= #1 {2'h0, wb_addr_i[20:10]}; + {`MC_BW_32, `MC_MEM_SIZE_128}: row_adr <= #1 {1'h0, wb_addr_i[21:10]}; + {`MC_BW_32, `MC_MEM_SIZE_256}: row_adr <= #1 wb_addr_i[22:10]; + endcase + end + + +always @(posedge clk) + if(cs_le) + begin + if(!bas) + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[12:11]; + {`MC_BW_8, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[13:12]; + {`MC_BW_8, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[13:12]; + + {`MC_BW_16, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[11:10]; + {`MC_BW_16, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[12:11]; + {`MC_BW_16, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[12:11]; + + {`MC_BW_32, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[11:10]; + {`MC_BW_32, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[11:10]; + {`MC_BW_32, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[11:10]; + endcase + else + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[24:23]; + {`MC_BW_8, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[25:24]; + {`MC_BW_8, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[26:25]; + + {`MC_BW_16, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[23:22]; + {`MC_BW_16, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[24:23]; + {`MC_BW_16, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[25:24]; + + {`MC_BW_32, `MC_MEM_SIZE_64}: bank_adr <= #1 wb_addr_i[22:21]; + {`MC_BW_32, `MC_MEM_SIZE_128}: bank_adr <= #1 wb_addr_i[23:22]; + {`MC_BW_32, `MC_MEM_SIZE_256}: bank_adr <= #1 wb_addr_i[24:23]; + endcase + end + +always @(bus_width or mem_size) + casex({bus_width, mem_size}) // synopsys full_case parallel_case + {`MC_BW_8, `MC_MEM_SIZE_64}: page_size = 11'd512; + {`MC_BW_8, `MC_MEM_SIZE_128}: page_size = 11'd1024; + {`MC_BW_8, `MC_MEM_SIZE_256}: page_size = 11'd1024; + + {`MC_BW_16, `MC_MEM_SIZE_64}: page_size = 11'd256; + {`MC_BW_16, `MC_MEM_SIZE_128}: page_size = 11'd512; + {`MC_BW_16, `MC_MEM_SIZE_256}: page_size = 11'd512; + + {`MC_BW_32, `MC_MEM_SIZE_64}: page_size = 11'd256; + {`MC_BW_32, `MC_MEM_SIZE_128}: page_size = 11'd256; + {`MC_BW_32, `MC_MEM_SIZE_256}: page_size = 11'd256; + endcase + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v new file mode 100644 index 000000000..04c7ce7c8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v @@ -0,0 +1,276 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Chip Select Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_cs_rf.v,v 1.6 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_cs_rf.v,v $ +// Revision 1.6 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.5 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.4 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.3 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:42 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_cs_rf(clk, rst, wb_we_i, din, rf_we, addr, csc, tms, poc, csc_mask, cs, + wp_err, lmr_req, lmr_ack, init_req, init_ack ); + +input clk, rst; +input wb_we_i; +input [31:0] din; +input rf_we; +input [31:0] addr; + +output [31:0] csc; +output [31:0] tms; +input [31:0] poc; +input [31:0] csc_mask; +output cs; +output wp_err; + +output lmr_req; +input lmr_ack; +output init_req; +input init_ack; + +parameter [2:0] this_cs = 0; +parameter [3:0] reg_select = this_cs + 2; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers and Wires +// + +reg [31:0] csc; +reg [31:0] tms; +wire sel; +wire cs_d; +wire wp; +reg inited; +reg init_req; +reg init_req_we; +reg lmr_req; +reg lmr_req_we; + +//////////////////////////////////////////////////////////////////// +// +// A kludge for cases where there is no clock during reset ... +// + +reg rst_r1, rst_r2; + +always @(posedge clk or posedge rst) + if(rst) rst_r1 <= #1 1'b1; + else rst_r1 <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) rst_r2 <= #1 1'b1; + else rst_r2 <= #1 rst_r1; + +//////////////////////////////////////////////////////////////////// +// +// Write Logic +// + +reg [6:0] addr_r; + +always @(posedge clk) + addr_r <= #1 addr[6:0]; + +assign sel = addr_r[6:3] == reg_select[3:0]; + +always @(posedge clk) + if(rst_r2) csc <= #1 (this_cs[2:0] == `MC_DEF_SEL) ? + {26'h0, poc[1:0], 1'b0, poc[3:2], (poc[3:2] != 2'b00)} : 32'h0; + else + if(rf_we & sel & !addr_r[2]) csc <= #1 din; + +always @(posedge clk) + if(rst_r2) tms <= #1 (this_cs[2:0] == `MC_DEF_SEL) ? + `MC_DEF_POR_TMS : 32'h0; + else + if(rf_we & sel & addr_r[2]) tms <= #1 din; + +//////////////////////////////////////////////////////////////////// +// +// Load Mode Register Request/Ack Logic +// +always @(posedge clk or posedge rst) + if(rst) lmr_req_we <= #1 1'b0; + else lmr_req_we <= #1 rf_we & sel & addr_r[2]; + +always @(posedge clk or posedge rst) + if(rst) lmr_req <= #1 1'b0; + else + if(lmr_req_we & (csc[3:1] == `MC_MEM_TYPE_SDRAM)) + lmr_req <= #1 inited; + else + if(lmr_ack) lmr_req <= #1 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// Initialize SDRAM Request/Ack & tracking logic +// +always @(posedge clk or posedge rst) + if(rst) init_req_we <= #1 1'b0; + else init_req_we <= #1 rf_we & sel & !addr_r[2]; + +always @(posedge clk or posedge rst) + if(rst) init_req <= #1 1'b0; + else + if(init_req_we & (csc[3:1] == `MC_MEM_TYPE_SDRAM) & csc[0] & !inited) + init_req <= #1 1'b1; + else + if(init_ack) init_req <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) inited <= #1 1'b0; + else + if(init_ack) inited <= #1 1'b1; + +//////////////////////////////////////////////////////////////////// +// +// Chip Select Generation Logic +// + +assign cs_d = ((csc[23:16] & csc_mask[7:0]) == (addr[28:21] & csc_mask[7:0])) & csc[0]; + +assign wp = wb_we_i & csc[8]; + +assign wp_err = cs_d & wp; +assign cs = cs_d & !wp; + +endmodule + + + +// This dummy is used to terminate the outputs for non existing Chip Selects +module mc_cs_rf_dummy(clk, rst, wb_we_i, din, rf_we, addr, csc, tms, poc, csc_mask, cs, + wp_err, lmr_req, lmr_ack, init_req, init_ack ); + +parameter [2:0] this_cs = 0; + +input clk, rst; +input wb_we_i; +input [31:0] din; +input rf_we; +input [31:0] addr; + +output [31:0] csc; +output [31:0] tms; +input [31:0] poc; +input [31:0] csc_mask; +output cs; +output wp_err; + +output lmr_req; +input lmr_ack; +output init_req; +input init_ack; + +assign csc = 32'h0; +assign tms = 32'h0; +assign cs = 1'b0; +assign wp_err = 1'b0; +assign lmr_req = 1'b0; +assign init_req = 1'b0; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v new file mode 100644 index 000000000..62a1c6900 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v @@ -0,0 +1,232 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Definitions //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_defines.v,v 1.7 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.7 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_defines.v,v $ +// Revision 1.7 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.6 2001/12/12 06:35:15 rudi +// *** empty log message *** +// +// Revision 1.5 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.4 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.3 2001/09/10 13:44:17 rudi +// *** empty log message *** +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug +// fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:38 rudi +// Created Directory Structure +// +// +// +// + +`timescale 1ns / 10ps + +///////////////////////////////////////////////////////////////////// +// +// This define selects how the WISHBONE interface determines if +// the internal register file is selected. +// This should be a simple address decoder. "wb_addr_i" is the +// WISHBONE address bus (32 bits wide). +`define MC_REG_SEL (wb_addr_i[31:29] == 3'b011) + +// This define selects how the WISHBONE interface determines if +// the memory is selected. +// This should be a simple address decoder. "wb_addr_i" is the +// WISHBONE address bus (32 bits wide). +`define MC_MEM_SEL (wb_addr_i[31:29] == 3'h0) + +///////////////////////////////////////////////////////////////////// +// +// This are the default Power-On Reset values for Chip Select +// + +// This will be defined by the run script for my test bench ... +// Alternatively force here for synthesis ... +//`define RUDIS_TB 1 + +// Defines which chip select is used for Power On booting + +// To run my default testbench default boot CS must be 3 !!! +`ifdef RUDIS_TB +`define MC_DEF_SEL 3'h3 +`else +`define MC_DEF_SEL 3'h0 +`endif + +// Defines the default (reset) TMS value for the DEF_SEL chip select +`define MC_DEF_POR_TMS 32'hffff_ffff + + +///////////////////////////////////////////////////////////////////// +// +// Define how many Chip Selects to Implement +// +`define MC_HAVE_CS1 1 +//`define MC_HAVE_CS2 1 +//`define MC_HAVE_CS3 1 +//`define MC_HAVE_CS4 1 +//`define MC_HAVE_CS5 1 +//`define MC_HAVE_CS6 1 +//`define MC_HAVE_CS7 1 + + +// To run my default testbench those need to there !!! +`ifdef RUDIS_TB +`define MC_HAVE_CS2 1 +`define MC_HAVE_CS3 1 +`define MC_HAVE_CS4 1 +`define MC_HAVE_CS5 1 +`endif + +///////////////////////////////////////////////////////////////////// +// +// Init Refresh +// +// Number of Refresh Cycles to perform during SDRAM initialization. +// This varies between SDRAM manufacturer. Typically this value is +// between 2 and 8. This number must be smaller than 16. +`define MC_INIT_RFRC_CNT 2 + +///////////////////////////////////////////////////////////////////// +// +// Power On Delay +// +// Most if SDRAMs require some time to initialize before they can be used +// after power on. If the Memory Controller shall stall after power on to +// allow SDRAMs to finish the initialization process uncomment the below +// define statement +`define MC_POR_DELAY 1 + +// This value defines how many MEM_CLK cycles the Memory Controller should +// stall. Default is 2.5uS. At a 10nS MEM_CLK cycle time, this would 250 +// cycles. +`define MC_POR_DELAY_VAL 8'd250 + + +// =============================================================== +// =============================================================== +// Various internal defines (DO NOT MODIFY !) +// =============================================================== +// =============================================================== + +// Register settings encodings +`define MC_BW_8 2'h0 +`define MC_BW_16 2'h1 +`define MC_BW_32 2'h2 + +`define MC_MEM_TYPE_SDRAM 3'h0 +`define MC_MEM_TYPE_SRAM 3'h1 +`define MC_MEM_TYPE_ACS 3'h2 +`define MC_MEM_TYPE_SCS 3'h3 + +`define MC_MEM_SIZE_64 2'h0 +`define MC_MEM_SIZE_128 2'h1 +`define MC_MEM_SIZE_256 2'h2 + +// Command Valid, Ras_, Cas_, We_ +`define MC_CMD_NOP 4'b0111 +`define MC_CMD_PC 4'b1010 +`define MC_CMD_ACT 4'b1011 +`define MC_CMD_WR 4'b1100 +`define MC_CMD_RD 4'b1101 +`define MC_CMD_BT 4'b1110 +`define MC_CMD_ARFR 4'b1001 +`define MC_CMD_LMR 4'b1000 +`define MC_CMD_XRD 4'b1111 +`define MC_CMD_XWR 4'b1110 + +`define MC_SINGLE_BANK 1'b0 +`define MC_ALL_BANKS 1'b1 + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v new file mode 100644 index 000000000..f172db514 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v @@ -0,0 +1,244 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Data Path Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_dp.v,v 1.6 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_dp.v,v $ +// Revision 1.6 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.5 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.4 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.3 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:47 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_dp( clk, rst, csc, + wb_cyc_i, wb_stb_i, wb_ack_o, mem_ack, wb_data_i, wb_data_o, + wb_read_go, wb_we_i, + mc_clk, mc_data_del, mc_dp_i, mc_data_o, mc_dp_o, + + dv, pack_le0, pack_le1, pack_le2, + byte_en, par_err + ); + +input clk, rst; +input [31:0] csc; + +input wb_cyc_i; +input wb_stb_i; +input mem_ack; +input wb_ack_o; +input [31:0] wb_data_i; +output [31:0] wb_data_o; +input wb_read_go; +input wb_we_i; + +input mc_clk; +input [35:0] mc_data_del; +input [3:0] mc_dp_i; +output [31:0] mc_data_o; +output [3:0] mc_dp_o; + +input dv; +input pack_le0, pack_le1, pack_le2; // Pack Latch Enable +input [3:0] byte_en; // High Active byte enables +output par_err; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg [31:0] wb_data_o; +reg [31:0] mc_data_o; +wire [35:0] rd_fifo_out; +wire rd_fifo_clr; +reg [3:0] mc_dp_o; +reg par_err_r; + +reg [7:0] byte0, byte1, byte2; +reg [31:0] mc_data_d; + +wire [2:0] mem_type; +wire [1:0] bus_width; +wire pen; +wire re; + +// Aliases +assign mem_type = csc[3:1]; +assign bus_width = csc[5:4]; +assign pen = csc[11]; + +//////////////////////////////////////////////////////////////////// +// +// WB READ Data Path +// + +always @(mem_type or rd_fifo_out or mc_data_d) + if( (mem_type == `MC_MEM_TYPE_SDRAM) | + (mem_type == `MC_MEM_TYPE_SRAM) ) wb_data_o = rd_fifo_out[31:0]; + else wb_data_o = mc_data_d; + +//assign rd_fifo_clr = !(rst | !wb_cyc_i | (wb_we_i & wb_stb_i) ); +assign rd_fifo_clr = !wb_cyc_i | (wb_we_i & wb_stb_i); +assign re = wb_ack_o & wb_read_go; + +mc_rd_fifo u0( + .clk( clk ), + .rst( rst ), + .clr( rd_fifo_clr ), + .din( mc_data_del ), + .we( dv ), + .dout( rd_fifo_out ), + .re( re ) + ); + +//////////////////////////////////////////////////////////////////// +// +// WB WRITE Data Path +// + +always @(posedge clk) + if(wb_ack_o | (mem_type != `MC_MEM_TYPE_SDRAM) ) + mc_data_o <= #1 wb_data_i; + +//////////////////////////////////////////////////////////////////// +// +// Read Data Packing +// + +always @(posedge clk) + if(pack_le0) byte0 <= #1 mc_data_del[7:0]; + +always @(posedge clk) + if(pack_le1 & (bus_width == `MC_BW_8)) byte1 <= #1 mc_data_del[7:0]; + else + if(pack_le0 & (bus_width == `MC_BW_16)) byte1 <= #1 mc_data_del[15:8]; + +always @(posedge clk) + if(pack_le2) byte2 <= #1 mc_data_del[7:0]; + +always @(bus_width or mc_data_del or byte0 or byte1 or byte2) + if(bus_width == `MC_BW_8) mc_data_d = {mc_data_del[7:0], byte2, byte1, byte0}; + else + if(bus_width == `MC_BW_16) mc_data_d = {mc_data_del[15:0], byte1, byte0}; + else mc_data_d = mc_data_del[31:0]; + +//////////////////////////////////////////////////////////////////// +// +// Parity Generation +// + +always @(posedge clk) + if(wb_ack_o | (mem_type != `MC_MEM_TYPE_SDRAM) ) + mc_dp_o <= #1 { ^wb_data_i[31:24], ^wb_data_i[23:16], + ^wb_data_i[15:08], ^wb_data_i[07:00] }; + +//////////////////////////////////////////////////////////////////// +// +// Parity Checking +// + +assign par_err = !wb_we_i & mem_ack & pen & ( + (( ^rd_fifo_out[31:24] ^ rd_fifo_out[35] ) & byte_en[3] ) | + (( ^rd_fifo_out[23:16] ^ rd_fifo_out[34] ) & byte_en[2] ) | + (( ^rd_fifo_out[15:08] ^ rd_fifo_out[33] ) & byte_en[1] ) | + (( ^rd_fifo_out[07:00] ^ rd_fifo_out[32] ) & byte_en[0] ) + ); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v new file mode 100644 index 000000000..a058b0188 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Parametarized, Pipelined Incrementer //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_incn_r.v,v 1.2 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_incn_r.v,v $ +// Revision 1.2 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.1 2001/06/12 15:18:47 rudi +// +// +// This is a pipelined primitive incrementor. +// +// +// +// +// + +`include "mc_defines.v" + +// +// USAGE: incN_r #() uN(clk, input, output); +// +module mc_incn_r(clk, inc_in, inc_out); + +parameter incN_width = 32; + +input clk; +input [incN_width-1:0] inc_in; +output [incN_width-1:0] inc_out; + +parameter incN_center = incN_width / 2; + +reg [incN_center:0] out_r; +wire [31:0] tmp_zeros = 32'h0; +wire [incN_center-1:0] inc_next; + +always @(posedge clk) + out_r <= #1 inc_in[incN_center - 1:0] + {tmp_zeros[incN_center-2:0], 1'h1}; + +assign inc_out[incN_width-1:incN_center] = inc_in[incN_width-1:incN_center] + inc_next; + +assign inc_next = out_r[incN_center] ? + {tmp_zeros[incN_center-2:0], 1'h1} : tmp_zeros[incN_center-2:0]; + +assign inc_out[incN_center-1:0] = out_r; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v new file mode 100644 index 000000000..1bb40ec41 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v @@ -0,0 +1,362 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Memory Bus Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_mem_if.v,v 1.6 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_mem_if.v,v $ +// Revision 1.6 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.5 2001/12/21 05:09:29 rudi +// +// - Fixed combinatorial loops in synthesis +// - Fixed byte select bug +// +// Revision 1.4 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.3 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.2 2001/09/02 02:28:28 rudi +// +// Many fixes for minor bugs that showed up in gate level simulations. +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/14 01:57:37 rudi +// +// +// Fixed a potential bug in a corner case situation where the TMS register +// does not propegate properly during initialisation. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:48 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_mem_if(clk, rst, mc_clk, mc_br, mc_bg, + mc_addr, mc_data_o, mc_dp_o, mc_data_oe, + mc_dqm, mc_oe_, mc_we_, mc_cas_, mc_ras_, mc_cke_, mc_cs_, + mc_adsc_, mc_adv_, mc_ack, mc_rp, mc_c_oe, mc_c_oe_d, + mc_br_r, mc_bg_d, mc_data_od, mc_dp_od, mc_addr_d, mc_ack_r, + we_, ras_, cas_, cke_, mc_adsc_d, mc_adv_d, cs_en, rfr_ack, + cs_need_rfr, lmr_sel, spec_req_cs, cs, fs, data_oe, susp_sel, + suspended_o, oe_, wb_cyc_i, wb_stb_i, wb_sel_i, wb_cycle, + wr_cycle, mc_data_ir, mc_data_i, mc_dp_i, mc_sts_ir, mc_sts_i, + mc_zz_o + ); +// Memory Interface +input clk; +input rst; +input mc_clk; +input mc_br; +output mc_bg; +output [23:0] mc_addr; +output [31:0] mc_data_o; +output [3:0] mc_dp_o; +output mc_data_oe; +output [3:0] mc_dqm; +output mc_oe_; +output mc_we_; +output mc_cas_; +output mc_ras_; +output mc_cke_; +output [7:0] mc_cs_; +output mc_adsc_; +output mc_adv_; +input mc_ack; +output mc_rp; +output mc_c_oe; +output [35:0] mc_data_ir; +output mc_sts_ir; +output mc_zz_o; + +// Internal Interface +output mc_br_r; +input mc_bg_d; +input data_oe; +input susp_sel; +input suspended_o; +input [31:0] mc_data_od; +input [3:0] mc_dp_od; +input [23:0] mc_addr_d; +output mc_ack_r; +input wb_cyc_i; +input wb_stb_i; +input [3:0] wb_sel_i; +input wb_cycle; +input wr_cycle; +input oe_ ; +input we_; +input ras_; +input cas_; +input cke_; +input cs_en; +input rfr_ack; +input [7:0] cs_need_rfr; +input lmr_sel; +input [7:0] spec_req_cs; +input [7:0] cs; +input fs; +input mc_adsc_d; +input mc_adv_d; +input mc_c_oe_d; +input [31:0] mc_data_i; +input [3:0] mc_dp_i; +input mc_sts_i; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg mc_data_oe; +reg [31:0] mc_data_o; +reg [3:0] mc_dp_o; +reg [3:0] mc_dqm; +reg [3:0] mc_dqm_r; +reg [23:0] mc_addr; +reg mc_oe_; +reg mc_we_; +reg mc_cas_; +reg mc_ras_; +wire mc_cke_; +reg [7:0] mc_cs_; +reg mc_bg; +reg mc_adsc_; +reg mc_adv_; +reg mc_br_r; +reg mc_ack_r; +reg mc_rp; +reg mc_c_oe; +reg mc_zz_o; + +reg [35:0] mc_data_ir; +reg mc_sts_ir; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge mc_clk) + mc_zz_o <= #1 suspended_o; + +always @(posedge mc_clk) + mc_sts_ir <= #1 mc_sts_i; + +always @(posedge mc_clk) + mc_data_ir <= #1 {mc_dp_i, mc_data_i}; + +always @(posedge mc_clk) + mc_c_oe <= #1 mc_c_oe_d; + +always @(posedge mc_clk) + mc_rp <= #1 !suspended_o & !fs; + +always @(posedge mc_clk) + mc_br_r <= #1 mc_br; + +always @(posedge mc_clk) + mc_ack_r <= #1 mc_ack; + +always @(posedge mc_clk) + mc_bg <= #1 mc_bg_d; + +always @(posedge mc_clk or posedge rst) + if(rst) mc_data_oe <= #1 1'b0; + else mc_data_oe <= #1 data_oe & !susp_sel & mc_c_oe_d; + +always @(posedge mc_clk) + mc_data_o <= #1 mc_data_od; + +always @(posedge mc_clk) + mc_dp_o <= #1 mc_dp_od; + +always @(posedge mc_clk) + mc_addr <= #1 mc_addr_d; + +always @(posedge clk) + if(wb_cyc_i & wb_stb_i) + mc_dqm_r <= #1 wb_sel_i; + +reg [3:0] mc_dqm_r2; +always @(posedge clk) + mc_dqm_r2 <= #1 mc_dqm_r; + +always @(posedge mc_clk) + mc_dqm <= #1 susp_sel ? 4'hf : + data_oe ? ~mc_dqm_r2 : + (wb_cycle & !wr_cycle) ? 4'h0 : 4'hf; + +always @(posedge mc_clk or posedge rst) + if(rst) mc_oe_ <= #1 1'b1; + else mc_oe_ <= #1 oe_ | susp_sel; + +always @(posedge mc_clk) + mc_we_ <= #1 we_; + +always @(posedge mc_clk) + mc_cas_ <= #1 cas_; + +always @(posedge mc_clk) + mc_ras_ <= #1 ras_; + +assign mc_cke_ = cke_; + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[0] <= #1 1'b1; + else + mc_cs_[0] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[0] : + lmr_sel ? spec_req_cs[0] : + cs[0] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[1] <= #1 1'b1; + else + mc_cs_[1] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[1] : + lmr_sel ? spec_req_cs[1] : + cs[1] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[2] <= #1 1'b1; + else + mc_cs_[2] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[2] : + lmr_sel ? spec_req_cs[2] : + cs[2] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[3] <= #1 1'b1; + else + mc_cs_[3] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[3] : + lmr_sel ? spec_req_cs[3] : + cs[3] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[4] <= #1 1'b1; + else + mc_cs_[4] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[4] : + lmr_sel ? spec_req_cs[4] : + cs[4] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[5] <= #1 1'b1; + else + mc_cs_[5] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[5] : + lmr_sel ? spec_req_cs[5] : + cs[5] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[6] <= #1 1'b1; + else + mc_cs_[6] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[6] : + lmr_sel ? spec_req_cs[6] : + cs[6] + )); + +always @(posedge mc_clk or posedge rst) + if(rst) mc_cs_[7] <= #1 1'b1; + else + mc_cs_[7] <= #1 ~(cs_en & ( + (rfr_ack | susp_sel) ? cs_need_rfr[7] : + lmr_sel ? spec_req_cs[7] : + cs[7] + )); + +always @(posedge mc_clk) + mc_adsc_ <= #1 ~mc_adsc_d; + +always @(posedge mc_clk) + mc_adv_ <= #1 ~mc_adv_d; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v new file mode 100644 index 000000000..5890d7fb3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v @@ -0,0 +1,236 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Open Bank & Row Tracking Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_obct.v,v 1.4 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_obct.v,v $ +// Revision 1.4 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.3 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.2 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:45 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_obct(clk, rst, row_adr, bank_adr, bank_set, bank_clr, bank_clr_all, + bank_open, any_bank_open, row_same); +input clk, rst; +input [12:0] row_adr; +input [1:0] bank_adr; +input bank_set; +input bank_clr; +input bank_clr_all; +output bank_open; +output any_bank_open; +output row_same; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg bank0_open, bank1_open, bank2_open, bank3_open; +reg bank_open; +reg [12:0] b0_last_row; +reg [12:0] b1_last_row; +reg [12:0] b2_last_row; +reg [12:0] b3_last_row; +wire row0_same, row1_same, row2_same, row3_same; +reg row_same; + +//////////////////////////////////////////////////////////////////// +// +// Bank Open/Closed Tracking +// + +always @(posedge clk or posedge rst) + if(rst) bank0_open <= #1 1'b0; + else + if((bank_adr == 2'h0) & bank_set) bank0_open <= #1 1'b1; + else + if((bank_adr == 2'h0) & bank_clr) bank0_open <= #1 1'b0; + else + if(bank_clr_all) bank0_open <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) bank1_open <= #1 1'b0; + else + if((bank_adr == 2'h1) & bank_set) bank1_open <= #1 1'b1; + else + if((bank_adr == 2'h1) & bank_clr) bank1_open <= #1 1'b0; + else + if(bank_clr_all) bank1_open <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) bank2_open <= #1 1'b0; + else + if((bank_adr == 2'h2) & bank_set) bank2_open <= #1 1'b1; + else + if((bank_adr == 2'h2) & bank_clr) bank2_open <= #1 1'b0; + else + if(bank_clr_all) bank2_open <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) bank3_open <= #1 1'b0; + else + if((bank_adr == 2'h3) & bank_set) bank3_open <= #1 1'b1; + else + if((bank_adr == 2'h3) & bank_clr) bank3_open <= #1 1'b0; + else + if(bank_clr_all) bank3_open <= #1 1'b0; + +always @(bank_adr or bank0_open or bank1_open or bank2_open or bank3_open) + case(bank_adr) // synopsys full_case parallel_case + 2'h0: bank_open = bank0_open; + 2'h1: bank_open = bank1_open; + 2'h2: bank_open = bank2_open; + 2'h3: bank_open = bank3_open; + endcase + +assign any_bank_open = bank0_open | bank1_open | bank2_open | bank3_open; + +//////////////////////////////////////////////////////////////////// +// +// Raw Address Tracking +// + +always @(posedge clk) + if((bank_adr == 2'h0) & bank_set) b0_last_row <= #1 row_adr; + +always @(posedge clk) + if((bank_adr == 2'h1) & bank_set) b1_last_row <= #1 row_adr; + +always @(posedge clk) + if((bank_adr == 2'h2) & bank_set) b2_last_row <= #1 row_adr; + +always @(posedge clk) + if((bank_adr == 2'h3) & bank_set) b3_last_row <= #1 row_adr; + +//////////////////////////////////////////////////////////////////// +// +// Raw address checking +// + +assign row0_same = (b0_last_row == row_adr); +assign row1_same = (b1_last_row == row_adr); +assign row2_same = (b2_last_row == row_adr); +assign row3_same = (b3_last_row == row_adr); + +always @(bank_adr or row0_same or row1_same or row2_same or row3_same) + case(bank_adr) // synopsys full_case parallel_case + 2'h0: row_same = row0_same; + 2'h1: row_same = row1_same; + 2'h2: row_same = row2_same; + 2'h3: row_same = row3_same; + endcase + +endmodule + + +// This is used for unused Chip Selects +module mc_obct_dummy(clk, rst, row_adr, bank_adr, bank_set, bank_clr, bank_clr_all, + bank_open, any_bank_open, row_same); +input clk, rst; +input [12:0] row_adr; +input [1:0] bank_adr; +input bank_set; +input bank_clr; +input bank_clr_all; +output bank_open; +output any_bank_open; +output row_same; + +assign bank_open = 1'b0; +assign any_bank_open = 1'b0; +assign row_same = 1'b0; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v new file mode 100644 index 000000000..26d230190 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v @@ -0,0 +1,426 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Open Bank & Row Tracking Block Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_obct_top.v,v 1.4 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_obct_top.v,v $ +// Revision 1.4 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.3 2001/12/21 05:09:29 rudi +// +// - Fixed combinatorial loops in synthesis +// - Fixed byte select bug +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.1.1.1 2001/05/13 09:39:47 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_obct_top(clk, rst, cs, row_adr, bank_adr, bank_set, bank_clr, bank_clr_all, + bank_open, any_bank_open, row_same, rfr_ack); +input clk, rst; +input [7:0] cs; +input [12:0] row_adr; +input [1:0] bank_adr; +input bank_set; +input bank_clr; +input bank_clr_all; +output bank_open; +output any_bank_open; +output row_same; +input rfr_ack; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg bank_open; +reg row_same; +reg any_bank_open; + +wire bank_set_0; +wire bank_clr_0; +wire bank_clr_all_0; +wire bank_open_0; +wire row_same_0; +wire any_bank_open_0; + +wire bank_set_1; +wire bank_clr_1; +wire bank_clr_all_1; +wire bank_open_1; +wire row_same_1; +wire any_bank_open_1; + +wire bank_set_2; +wire bank_clr_2; +wire bank_clr_all_2; +wire bank_open_2; +wire row_same_2; +wire any_bank_open_2; + +wire bank_set_3; +wire bank_clr_3; +wire bank_clr_all_3; +wire bank_open_3; +wire row_same_3; +wire any_bank_open_3; + +wire bank_set_4; +wire bank_clr_4; +wire bank_clr_all_4; +wire bank_open_4; +wire row_same_4; +wire any_bank_open_4; + +wire bank_set_5; +wire bank_clr_5; +wire bank_clr_all_5; +wire bank_open_5; +wire row_same_5; +wire any_bank_open_5; + +wire bank_set_6; +wire bank_clr_6; +wire bank_clr_all_6; +wire bank_open_6; +wire row_same_6; +wire any_bank_open_6; + +wire bank_set_7; +wire bank_clr_7; +wire bank_clr_all_7; +wire bank_open_7; +wire row_same_7; +wire any_bank_open_7; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign bank_set_0 = cs[0] & bank_set; +assign bank_set_1 = cs[1] & bank_set; +assign bank_set_2 = cs[2] & bank_set; +assign bank_set_3 = cs[3] & bank_set; +assign bank_set_4 = cs[4] & bank_set; +assign bank_set_5 = cs[5] & bank_set; +assign bank_set_6 = cs[6] & bank_set; +assign bank_set_7 = cs[7] & bank_set; + +assign bank_clr_0 = cs[0] & bank_clr; +assign bank_clr_1 = cs[1] & bank_clr; +assign bank_clr_2 = cs[2] & bank_clr; +assign bank_clr_3 = cs[3] & bank_clr; +assign bank_clr_4 = cs[4] & bank_clr; +assign bank_clr_5 = cs[5] & bank_clr; +assign bank_clr_6 = cs[6] & bank_clr; +assign bank_clr_7 = cs[7] & bank_clr; + +assign bank_clr_all_0 = (cs[0] & bank_clr_all) | rfr_ack; +assign bank_clr_all_1 = (cs[1] & bank_clr_all) | rfr_ack; +assign bank_clr_all_2 = (cs[2] & bank_clr_all) | rfr_ack; +assign bank_clr_all_3 = (cs[3] & bank_clr_all) | rfr_ack; +assign bank_clr_all_4 = (cs[4] & bank_clr_all) | rfr_ack; +assign bank_clr_all_5 = (cs[5] & bank_clr_all) | rfr_ack; +assign bank_clr_all_6 = (cs[6] & bank_clr_all) | rfr_ack; +assign bank_clr_all_7 = (cs[7] & bank_clr_all) | rfr_ack; + +always @(posedge clk) + bank_open <= #1 (cs[0] & bank_open_0) | (cs[1] & bank_open_1) | + (cs[2] & bank_open_2) | (cs[3] & bank_open_3) | + (cs[4] & bank_open_4) | (cs[5] & bank_open_5) | + (cs[6] & bank_open_6) | (cs[7] & bank_open_7); + +always @(posedge clk) + row_same <= #1 (cs[0] & row_same_0) | (cs[1] & row_same_1) | + (cs[2] & row_same_2) | (cs[3] & row_same_3) | + (cs[4] & row_same_4) | (cs[5] & row_same_5) | + (cs[6] & row_same_6) | (cs[7] & row_same_7); + +always @(posedge clk) + any_bank_open <= #1 (cs[0] & any_bank_open_0) | (cs[1] & any_bank_open_1) | + (cs[2] & any_bank_open_2) | (cs[3] & any_bank_open_3) | + (cs[4] & any_bank_open_4) | (cs[5] & any_bank_open_5) | + (cs[6] & any_bank_open_6) | (cs[7] & any_bank_open_7); + + +//////////////////////////////////////////////////////////////////// +// +// OBCT Modules for each Chip Select +// + +mc_obct u0( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_0 ), + .bank_clr( bank_clr_0 ), + .bank_clr_all( bank_clr_all_0 ), + .bank_open( bank_open_0 ), + .any_bank_open( any_bank_open_0 ), + .row_same( row_same_0 ) + ); + +`ifdef MC_HAVE_CS1 +mc_obct u1( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_1 ), + .bank_clr( bank_clr_1 ), + .bank_clr_all( bank_clr_all_1 ), + .bank_open( bank_open_1 ), + .any_bank_open( any_bank_open_1 ), + .row_same( row_same_1 ) + ); +`else +mc_obct_dummy u1( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_1 ), + .bank_clr( bank_clr_1 ), + .bank_clr_all( bank_clr_all_1 ), + .bank_open( bank_open_1 ), + .any_bank_open( any_bank_open_1 ), + .row_same( row_same_1 ) + ); +`endif + +`ifdef MC_HAVE_CS2 +mc_obct u2( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_2 ), + .bank_clr( bank_clr_2 ), + .bank_clr_all( bank_clr_all_2 ), + .bank_open( bank_open_2 ), + .any_bank_open( any_bank_open_2 ), + .row_same( row_same_2 ) + ); +`else +mc_obct_dummy u2( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_2 ), + .bank_clr( bank_clr_2 ), + .bank_clr_all( bank_clr_all_2 ), + .bank_open( bank_open_2 ), + .any_bank_open( any_bank_open_2 ), + .row_same( row_same_2 ) + ); +`endif + +`ifdef MC_HAVE_CS3 +mc_obct u3( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_3 ), + .bank_clr( bank_clr_3 ), + .bank_clr_all( bank_clr_all_3 ), + .bank_open( bank_open_3 ), + .any_bank_open( any_bank_open_3 ), + .row_same( row_same_3 ) + ); +`else +mc_obct_dummy u3( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_3 ), + .bank_clr( bank_clr_3 ), + .bank_clr_all( bank_clr_all_3 ), + .bank_open( bank_open_3 ), + .any_bank_open( any_bank_open_3 ), + .row_same( row_same_3 ) + ); +`endif + +`ifdef MC_HAVE_CS4 +mc_obct u4( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_4 ), + .bank_clr( bank_clr_4 ), + .bank_clr_all( bank_clr_all_4 ), + .bank_open( bank_open_4 ), + .any_bank_open( any_bank_open_4 ), + .row_same( row_same_4 ) + ); +`else +mc_obct_dummy u4( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_4 ), + .bank_clr( bank_clr_4 ), + .bank_clr_all( bank_clr_all_4 ), + .bank_open( bank_open_4 ), + .any_bank_open( any_bank_open_4 ), + .row_same( row_same_4 ) + ); +`endif + +`ifdef MC_HAVE_CS5 +mc_obct u5( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_5 ), + .bank_clr( bank_clr_5 ), + .bank_clr_all( bank_clr_all_5 ), + .bank_open( bank_open_5 ), + .any_bank_open( any_bank_open_5 ), + .row_same( row_same_5 ) + ); +`else +mc_obct_dummy u5( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_5 ), + .bank_clr( bank_clr_5 ), + .bank_clr_all( bank_clr_all_5 ), + .bank_open( bank_open_5 ), + .any_bank_open( any_bank_open_5 ), + .row_same( row_same_5 ) + ); +`endif + +`ifdef MC_HAVE_CS6 +mc_obct u6( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_6 ), + .bank_clr( bank_clr_6 ), + .bank_clr_all( bank_clr_all_6 ), + .bank_open( bank_open_6 ), + .any_bank_open( any_bank_open_6 ), + .row_same( row_same_6 ) + ); +`else +mc_obct_dummy u6( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_6 ), + .bank_clr( bank_clr_6 ), + .bank_clr_all( bank_clr_all_6 ), + .bank_open( bank_open_6 ), + .any_bank_open( any_bank_open_6 ), + .row_same( row_same_6 ) + ); +`endif + +`ifdef MC_HAVE_CS7 +mc_obct u7( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_7 ), + .bank_clr( bank_clr_7 ), + .bank_clr_all( bank_clr_all_7 ), + .bank_open( bank_open_7 ), + .any_bank_open( any_bank_open_7 ), + .row_same( row_same_7 ) + ); +`else +mc_obct_dummy u7( + .clk( clk ), + .rst( rst ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set_7 ), + .bank_clr( bank_clr_7 ), + .bank_clr_all( bank_clr_all_7 ), + .bank_open( bank_open_7 ), + .any_bank_open( any_bank_open_7 ), + .row_same( row_same_7 ) + ); +`endif + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v new file mode 100644 index 000000000..55de0c0f4 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v @@ -0,0 +1,130 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Read FIFO //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_rd_fifo.v,v 1.4 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_rd_fifo.v,v $ +// Revision 1.4 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.3 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.2 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.1.1.1 2001/05/13 09:39:44 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_rd_fifo(clk, rst, clr, din, we, dout, re); + +input clk, rst, clr; +input [35:0] din; +input we; +output [35:0] dout; +input re; + +reg [3:0] rd_adr, wr_adr; +reg [35:0] r0, r1, r2, r3; +reg [35:0] dout; + +always @(posedge clk or posedge rst) + if(rst) rd_adr <= #1 4'h1; + else + if(clr) rd_adr <= #1 4'h1; + else + if(re) rd_adr <= #1 {rd_adr[2:0], rd_adr[3]}; + +always @(posedge clk or posedge rst) + if(rst) wr_adr <= #1 4'h1; + else + if(clr) wr_adr <= #1 4'h1; + else + if(we) wr_adr <= #1 {wr_adr[2:0], wr_adr[3]}; + +always @(posedge clk) + if(we & wr_adr[0]) r0 <= #1 din; + +always @(posedge clk) + if(we & wr_adr[1]) r1 <= #1 din; + +always @(posedge clk) + if(we & wr_adr[2]) r2 <= #1 din; + +always @(posedge clk) + if(we & wr_adr[3]) r3 <= #1 din; + +always @(rd_adr or r0 or r1 or r2 or r3 or re or we or din) + case(rd_adr) // synopsys full_case parallel_case + 4'h1: dout = r0; + 4'h2: dout = r1; + 4'h4: dout = r2; + 4'h8: dout = r3; + endcase + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v new file mode 100644 index 000000000..b824fa4f7 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v @@ -0,0 +1,210 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// Refresh Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_refresh.v,v 1.4 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_refresh.v,v $ +// Revision 1.4 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.3 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.2 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:47 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_refresh(clk, rst, + cs_need_rfr, ref_int, rfr_req, rfr_ack, + rfr_ps_val + ); + +input clk, rst; +input [7:0] cs_need_rfr; +input [2:0] ref_int; +output rfr_req; +input rfr_ack; +input [7:0] rfr_ps_val; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg rfr_en; +reg [7:0] ps_cnt; +wire ps_cnt_clr; +reg rfr_ce; +reg [7:0] rfr_cnt; +reg rfr_clr; +reg rfr_req; +reg rfr_early; + +/* +Refresh generation + +The prescaler generates a 0.48828 uS clock enable + +The refresh counter generates the following refresh rates: +(Actual values are about 0.63% below the desired values). +This is for a 200 Mhz WISHBONE Bus. +0.970 uS, +1.940 +3.880 +7.760 +15.520 +32.040 +62.080 +124.160 uS + +(desired values) +0.976 uS +1.953 +3.906 +7.812 +15.625 +31.250 +62.500 +125.000 uS +*/ + +//////////////////////////////////////////////////////////////////// +// +// Prescaler +// + +always @(posedge clk or posedge rst) + if(rst) rfr_en <= #1 1'b0; + else rfr_en <= #1 |cs_need_rfr; + +always @(posedge clk or posedge rst) + if(rst) ps_cnt <= #1 8'h0; + else + if(ps_cnt_clr) ps_cnt <= #1 8'h0; + else + if(rfr_en) ps_cnt <= #1 ps_cnt + 8'h1; + +assign ps_cnt_clr = (ps_cnt == rfr_ps_val) & (rfr_ps_val != 8'h0); + +always @(posedge clk or posedge rst) + if(rst) rfr_early <= #1 1'b0; + else rfr_early <= #1 (ps_cnt == rfr_ps_val); + +//////////////////////////////////////////////////////////////////// +// +// Refresh Counter +// + +always @(posedge clk or posedge rst) + if(rst) rfr_ce <= #1 1'b0; + else rfr_ce <= #1 ps_cnt_clr; + +always @(posedge clk or posedge rst) + if(rst) rfr_cnt <= #1 8'h0; + else + if(rfr_ack) rfr_cnt <= #1 8'h0; + else + if(rfr_ce) rfr_cnt <= #1 rfr_cnt + 8'h1; + +always @(posedge clk) + case(ref_int) // synopsys full_case parallel_case + 3'h0: rfr_clr <= #1 rfr_cnt[0] & rfr_early; + 3'h1: rfr_clr <= #1 &rfr_cnt[1:0] & rfr_early; + 3'h2: rfr_clr <= #1 &rfr_cnt[2:0] & rfr_early; + 3'h3: rfr_clr <= #1 &rfr_cnt[3:0] & rfr_early; + 3'h4: rfr_clr <= #1 &rfr_cnt[4:0] & rfr_early; + 3'h5: rfr_clr <= #1 &rfr_cnt[5:0] & rfr_early; + 3'h6: rfr_clr <= #1 &rfr_cnt[6:0] & rfr_early; + 3'h7: rfr_clr <= #1 &rfr_cnt[7:0] & rfr_early; + endcase + +always @(posedge clk or posedge rst) + if(rst) rfr_req <= #1 1'b0; + else + if(rfr_ack) rfr_req <= #1 1'b0; + else + if(rfr_clr) rfr_req <= #1 1'b1; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v new file mode 100644 index 000000000..8a1d3da9f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v @@ -0,0 +1,836 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_rf.v,v 1.8 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.8 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_rf.v,v $ +// Revision 1.8 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.7 2001/12/21 05:09:29 rudi +// +// - Fixed combinatorial loops in synthesis +// - Fixed byte select bug +// +// Revision 1.6 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.5 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.4 2001/10/04 03:19:37 rudi +// +// Fixed Register reads +// Tightened up timing for register rd/wr +// +// Revision 1.3 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:42 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_rf(clk, rst, + + wb_data_i, rf_dout, wb_addr_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wp_err, + + csc, tms, poc, + sp_csc, sp_tms, cs, + mc_data_i, mc_sts, mc_vpen, fs, + + cs_le_d, cs_le, cs_need_rfr, ref_int, rfr_ps_val, init_req, + init_ack, lmr_req, lmr_ack, + spec_req_cs + ); + +input clk, rst; + +// -------------------------------------- +// WISHBONE INTERFACE + +// Slave Interface +input [31:0] wb_data_i; +output [31:0] rf_dout; +input [31:0] wb_addr_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wp_err; + +// -------------------------------------- +// Misc Signals +output [31:0] csc; +output [31:0] tms; +output [31:0] poc; +output [31:0] sp_csc; +output [31:0] sp_tms; +output [7:0] cs; + +input [31:0] mc_data_i; +input mc_sts; +output mc_vpen; +output fs; + +input cs_le_d; +input cs_le; + +output [7:0] cs_need_rfr; // Indicates which chip selects have SDRAM + // attached and need to be refreshed +output [2:0] ref_int; // Refresh Interval +output [7:0] rfr_ps_val; + +output init_req; +input init_ack; +output lmr_req; +input lmr_ack; + +output [7:0] spec_req_cs; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg wb_ack_o; + +reg [31:0] csc; +reg [31:0] tms; +reg [31:0] sp_csc; +reg [31:0] sp_tms; +reg [31:0] rf_dout; +reg [7:0] cs; + +reg rf_we; +wire [31:0] csr; +reg [10:0] csr_r; +reg [7:0] csr_r2; +reg [31:0] poc; + +wire [31:0] csc_mask; +reg [10:0] csc_mask_r; + +wire [31:0] csc0, tms0; +wire [31:0] csc1, tms1; +wire [31:0] csc2, tms2; +wire [31:0] csc3, tms3; +wire [31:0] csc4, tms4; +wire [31:0] csc5, tms5; +wire [31:0] csc6, tms6; +wire [31:0] csc7, tms7; + +wire cs0, cs1, cs2, cs3; +wire cs4, cs5, cs6, cs7; +wire wp_err0, wp_err1, wp_err2, wp_err3; +wire wp_err4, wp_err5, wp_err6, wp_err7; +reg wp_err; + +wire lmr_req7, lmr_req6, lmr_req5, lmr_req4; +wire lmr_req3, lmr_req2, lmr_req1, lmr_req0; +wire lmr_ack7, lmr_ack6, lmr_ack5, lmr_ack4; +wire lmr_ack3, lmr_ack2, lmr_ack1, lmr_ack0; + +wire init_req7, init_req6, init_req5, init_req4; +wire init_req3, init_req2, init_req1, init_req0; +wire init_ack7, init_ack6, init_ack5, init_ack4; +wire init_ack3, init_ack2, init_ack1, init_ack0; + +reg init_ack_r; +wire init_ack_fe; +reg lmr_ack_r; +wire lmr_ack_fe; +wire [7:0] spec_req_cs_t; +wire [7:0] spec_req_cs_d; +reg [7:0] spec_req_cs; +reg init_req, lmr_req; +reg sreq_cs_le; + +// Aliases +assign csr = {csr_r2, 8'h0, 5'h0, csr_r}; +assign csc_mask = {21'h0, csc_mask_r}; + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Register Read logic +// + +always @(wb_addr_i or csr or poc or csc_mask or csc0 or tms0 or csc1 or + tms1 or csc2 or tms2 or csc3 or tms3 or csc4 or tms4 or csc5 or + tms5 or csc6 or tms6 or csc7 or tms7) + case(wb_addr_i[6:2]) // synopsys full_case parallel_case + 5'h00: rf_dout <= #1 csr; + 5'h01: rf_dout <= #1 poc; + 5'h02: rf_dout <= #1 csc_mask; + + 5'h04: rf_dout <= #1 csc0; + 5'h05: rf_dout <= #1 tms0; + 5'h06: rf_dout <= #1 csc1; + 5'h07: rf_dout <= #1 tms1; + 5'h08: rf_dout <= #1 csc2; + 5'h09: rf_dout <= #1 tms2; + 5'h0a: rf_dout <= #1 csc3; + 5'h0b: rf_dout <= #1 tms3; + 5'h0c: rf_dout <= #1 csc4; + 5'h0d: rf_dout <= #1 tms4; + 5'h0e: rf_dout <= #1 csc5; + 5'h0f: rf_dout <= #1 tms5; + 5'h10: rf_dout <= #1 csc6; + 5'h11: rf_dout <= #1 tms6; + 5'h12: rf_dout <= #1 csc7; + 5'h13: rf_dout <= #1 tms7; + endcase + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Register Write logic +// + +reg [6:0] wb_addr_r; + +always @(posedge clk) + wb_addr_r <= #1 wb_addr_i[6:0]; + +always @(posedge clk or posedge rst) + if(rst) rf_we <= #1 1'b0; + else rf_we <= #1 `MC_REG_SEL & wb_we_i & wb_cyc_i & wb_stb_i & !rf_we; + +always @(posedge clk or posedge rst) + if(rst) csr_r2 <= #1 8'h0; + else + if(rf_we & (wb_addr_r[6:2] == 5'h0) ) + csr_r2 <= #1 wb_data_i[31:24]; + +always @(posedge clk or posedge rst) + if(rst) csr_r[10:1] <= #1 10'h0; + else + if(rf_we & (wb_addr_r[6:2] == 5'h0) ) + csr_r[10:1] <= #1 wb_data_i[10:1]; + +always @(posedge clk) + csr_r[0] <= #1 mc_sts; + +assign mc_vpen = csr_r[1]; +assign fs = csr_r[2]; +assign rfr_ps_val = csr_r2[7:0]; + +always @(posedge clk or posedge rst) + if(rst) csc_mask_r <= #1 11'h7ff; + else + if(rf_we & (wb_addr_r[6:2] == 5'h2) ) + csc_mask_r <= #1 wb_data_i[10:0]; + +//////////////////////////////////////////////////////////////////// +// +// A kludge for cases where there is no clock during reset ... +// + +reg rst_r1, rst_r2, rst_r3; + +always @(posedge clk or posedge rst) + if(rst) rst_r1 <= #1 1'b1; + else rst_r1 <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) rst_r2 <= #1 1'b1; + else rst_r2 <= #1 rst_r1; + +always @(posedge clk or posedge rst) + if(rst) rst_r3 <= #1 1'b1; + else rst_r3 <= #1 rst_r2; + +always @(posedge clk) + if(rst_r3) poc <= #1 mc_data_i; + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Register Ack logic +// + +always @(posedge clk) + wb_ack_o <= #1 `MC_REG_SEL & wb_cyc_i & wb_stb_i & !wb_ack_o; + +//////////////////////////////////////////////////////////////////// +// +// Select CSC and TMS Registers +// + +always @(posedge clk or posedge rst) + if(rst) cs <= #1 8'h0; + else + if(cs_le) cs <= #1 {cs7, cs6, cs5, cs4, cs3, cs2, cs1, cs0}; + +always @(posedge clk or posedge rst) + if(rst) wp_err <= #1 1'b0; + else + if(cs_le & wb_cyc_i & wb_stb_i) + wp_err <= #1 wp_err7 | wp_err6 | wp_err5 | wp_err4 | + wp_err3 | wp_err2 | wp_err1 | wp_err0; + else + if(!wb_cyc_i) wp_err <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) csc <= #1 32'h0; + else + if(cs_le_d & wb_cyc_i & wb_stb_i) + begin + if(cs0) csc <= #1 csc0; + else + if(cs1) csc <= #1 csc1; + else + if(cs2) csc <= #1 csc2; + else + if(cs3) csc <= #1 csc3; + else + if(cs4) csc <= #1 csc4; + else + if(cs5) csc <= #1 csc5; + else + if(cs6) csc <= #1 csc6; + else csc <= #1 csc7; + end + +always @(posedge clk or posedge rst) + if(rst) tms <= #1 32'hffff_ffff; + else + if((cs_le_d | rf_we) & wb_cyc_i & wb_stb_i) + begin + if(cs0) tms <= #1 tms0; + else + if(cs1) tms <= #1 tms1; + else + if(cs2) tms <= #1 tms2; + else + if(cs3) tms <= #1 tms3; + else + if(cs4) tms <= #1 tms4; + else + if(cs5) tms <= #1 tms5; + else + if(cs6) tms <= #1 tms6; + else tms <= #1 tms7; + end + +always @(posedge clk or posedge rst) + if(rst) sp_csc <= #1 32'h0; + else + if(cs_le_d & wb_cyc_i & wb_stb_i) + begin + if(spec_req_cs[0]) sp_csc <= #1 csc0; + else + if(spec_req_cs[1]) sp_csc <= #1 csc1; + else + if(spec_req_cs[2]) sp_csc <= #1 csc2; + else + if(spec_req_cs[3]) sp_csc <= #1 csc3; + else + if(spec_req_cs[4]) sp_csc <= #1 csc4; + else + if(spec_req_cs[5]) sp_csc <= #1 csc5; + else + if(spec_req_cs[6]) sp_csc <= #1 csc6; + else sp_csc <= #1 csc7; + end + +always @(posedge clk or posedge rst) + if(rst) sp_tms <= #1 32'hffff_ffff; + else + if((cs_le_d | rf_we) & wb_cyc_i & wb_stb_i) + begin + if(spec_req_cs[0]) sp_tms <= #1 tms0; + else + if(spec_req_cs[1]) sp_tms <= #1 tms1; + else + if(spec_req_cs[2]) sp_tms <= #1 tms2; + else + if(spec_req_cs[3]) sp_tms <= #1 tms3; + else + if(spec_req_cs[4]) sp_tms <= #1 tms4; + else + if(spec_req_cs[5]) sp_tms <= #1 tms5; + else + if(spec_req_cs[6]) sp_tms <= #1 tms6; + else sp_tms <= #1 tms7; + end + +assign cs_need_rfr[0] = csc0[0] & (csc0[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[1] = csc1[0] & (csc1[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[2] = csc2[0] & (csc2[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[3] = csc3[0] & (csc3[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[4] = csc4[0] & (csc4[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[5] = csc5[0] & (csc5[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[6] = csc6[0] & (csc6[3:1] == `MC_MEM_TYPE_SDRAM); +assign cs_need_rfr[7] = csc7[0] & (csc7[3:1] == `MC_MEM_TYPE_SDRAM); + +assign ref_int = csr_r[10:8]; + +//////////////////////////////////////////////////////////////////// +// +// Init & Lmr Logic +// + +// Init Ack falling edge detector +always @(posedge clk) + init_ack_r <= #1 init_ack; + +assign init_ack_fe = init_ack_r & !init_ack; + +// LMR Ack falling edge detector +always @(posedge clk) + lmr_ack_r <= #1 lmr_ack; + +assign lmr_ack_fe = lmr_ack_r & !lmr_ack; + +// Chip Select Output +always @(posedge clk or posedge rst) + if(rst) spec_req_cs <= #1 8'h0; + else + if(sreq_cs_le) spec_req_cs <= #1 spec_req_cs_d; + +always @(posedge clk or posedge rst) + if(rst) sreq_cs_le <= #1 1'b0; + else sreq_cs_le <= #1 (!init_req & !lmr_req) | lmr_ack_fe | init_ack_fe; + +// Make sure only one is serviced at a time +assign spec_req_cs_d[0] = spec_req_cs_t[0]; +assign spec_req_cs_d[1] = spec_req_cs_t[1] & !spec_req_cs_t[0]; +assign spec_req_cs_d[2] = spec_req_cs_t[2] & !( |spec_req_cs_t[1:0] ); +assign spec_req_cs_d[3] = spec_req_cs_t[3] & !( |spec_req_cs_t[2:0] ); +assign spec_req_cs_d[4] = spec_req_cs_t[4] & !( |spec_req_cs_t[3:0] ); +assign spec_req_cs_d[5] = spec_req_cs_t[5] & !( |spec_req_cs_t[4:0] ); +assign spec_req_cs_d[6] = spec_req_cs_t[6] & !( |spec_req_cs_t[5:0] ); +assign spec_req_cs_d[7] = spec_req_cs_t[7] & !( |spec_req_cs_t[6:0] ); + +// Request Tracking +always @(posedge clk or posedge rst) + if(rst) init_req <= #1 1'b0; + else init_req <= #1 init_req0 | init_req1 | init_req2 | init_req3 | + init_req4 | init_req5 | init_req6 | init_req7; + +always @(posedge clk or posedge rst) + if(rst) lmr_req <= #1 1'b0; + else lmr_req <= #1 lmr_req0 | lmr_req1 | lmr_req2 | lmr_req3 | + lmr_req4 | lmr_req5 | lmr_req6 | lmr_req7; + +assign spec_req_cs_t = !init_req ? // Load Mode Register Requests + {lmr_req7, lmr_req6, lmr_req5, lmr_req4, + lmr_req3, lmr_req2, lmr_req1, lmr_req0 } : + // Initialize SDRAM Requests + {init_req7, init_req6, init_req5, init_req4, + init_req3, init_req2, init_req1, init_req0 }; + +// Ack distribution +assign lmr_ack0 = spec_req_cs[0] & lmr_ack_fe; +assign lmr_ack1 = spec_req_cs[1] & lmr_ack_fe; +assign lmr_ack2 = spec_req_cs[2] & lmr_ack_fe; +assign lmr_ack3 = spec_req_cs[3] & lmr_ack_fe; +assign lmr_ack4 = spec_req_cs[4] & lmr_ack_fe; +assign lmr_ack5 = spec_req_cs[5] & lmr_ack_fe; +assign lmr_ack6 = spec_req_cs[6] & lmr_ack_fe; +assign lmr_ack7 = spec_req_cs[7] & lmr_ack_fe; + +assign init_ack0 = spec_req_cs[0] & init_ack_fe; +assign init_ack1 = spec_req_cs[1] & init_ack_fe; +assign init_ack2 = spec_req_cs[2] & init_ack_fe; +assign init_ack3 = spec_req_cs[3] & init_ack_fe; +assign init_ack4 = spec_req_cs[4] & init_ack_fe; +assign init_ack5 = spec_req_cs[5] & init_ack_fe; +assign init_ack6 = spec_req_cs[6] & init_ack_fe; +assign init_ack7 = spec_req_cs[7] & init_ack_fe; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +mc_cs_rf #(3'h0) u0( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc0 ), + .tms( tms0 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs0 ), + .wp_err( wp_err0 ), + .lmr_req( lmr_req0 ), + .lmr_ack( lmr_ack0 ), + .init_req( init_req0 ), + .init_ack( init_ack0 ) + ); + +`ifdef MC_HAVE_CS1 +mc_cs_rf #(3'h1) u1( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc1 ), + .tms( tms1 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs1 ), + .wp_err( wp_err1 ), + .lmr_req( lmr_req1 ), + .lmr_ack( lmr_ack1 ), + .init_req( init_req1 ), + .init_ack( init_ack1 ) + ); +`else +mc_cs_rf_dummy #(3'h1) u1( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc1 ), + .tms( tms1 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs1 ), + .wp_err( wp_err1 ), + .lmr_req( lmr_req1 ), + .lmr_ack( lmr_ack1 ), + .init_req( init_req1 ), + .init_ack( init_ack1 ) + ); +`endif + +`ifdef MC_HAVE_CS2 +mc_cs_rf #(3'h2) u2( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc2 ), + .tms( tms2 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs2 ), + .wp_err( wp_err2 ), + .lmr_req( lmr_req2 ), + .lmr_ack( lmr_ack2 ), + .init_req( init_req2 ), + .init_ack( init_ack2 ) + ); +`else +mc_cs_rf_dummy #(3'h2) u2( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc2 ), + .tms( tms2 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs2 ), + .wp_err( wp_err2 ), + .lmr_req( lmr_req2 ), + .lmr_ack( lmr_ack2 ), + .init_req( init_req2 ), + .init_ack( init_ack2 ) + ); +`endif + +`ifdef MC_HAVE_CS3 +mc_cs_rf #(3'h3) u3( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc3 ), + .tms( tms3 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs3 ), + .wp_err( wp_err3 ), + .lmr_req( lmr_req3 ), + .lmr_ack( lmr_ack3 ), + .init_req( init_req3 ), + .init_ack( init_ack3 ) + ); +`else +mc_cs_rf_dummy #(3'h3) u3( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc3 ), + .tms( tms3 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs3 ), + .wp_err( wp_err3 ), + .lmr_req( lmr_req3 ), + .lmr_ack( lmr_ack3 ), + .init_req( init_req3 ), + .init_ack( init_ack3 ) + ); +`endif + +`ifdef MC_HAVE_CS4 +mc_cs_rf #(3'h4) u4( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc4 ), + .tms( tms4 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs4 ), + .wp_err( wp_err4 ), + .lmr_req( lmr_req4 ), + .lmr_ack( lmr_ack4 ), + .init_req( init_req4 ), + .init_ack( init_ack4 ) + ); +`else +mc_cs_rf_dummy #(3'h4) u4( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc4 ), + .tms( tms4 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs4 ), + .wp_err( wp_err4 ), + .lmr_req( lmr_req4 ), + .lmr_ack( lmr_ack4 ), + .init_req( init_req4 ), + .init_ack( init_ack4 ) + ); +`endif + +`ifdef MC_HAVE_CS5 +mc_cs_rf #(3'h5) u5( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc5 ), + .tms( tms5 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs5 ), + .wp_err( wp_err5 ), + .lmr_req( lmr_req5 ), + .lmr_ack( lmr_ack5 ), + .init_req( init_req5 ), + .init_ack( init_ack5 ) + ); +`else +mc_cs_rf_dummy #(3'h5) u5( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc5 ), + .tms( tms5 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs5 ), + .wp_err( wp_err5 ), + .lmr_req( lmr_req5 ), + .lmr_ack( lmr_ack5 ), + .init_req( init_req5 ), + .init_ack( init_ack5 ) + ); +`endif + +`ifdef MC_HAVE_CS6 +mc_cs_rf #(3'h6) u6( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc6 ), + .tms( tms6 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs6 ), + .wp_err( wp_err6 ), + .lmr_req( lmr_req6 ), + .lmr_ack( lmr_ack6 ), + .init_req( init_req6 ), + .init_ack( init_ack6 ) + ); +`else +mc_cs_rf_dummy #(3'h6) u6( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc6 ), + .tms( tms6 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs6 ), + .wp_err( wp_err6 ), + .lmr_req( lmr_req6 ), + .lmr_ack( lmr_ack6 ), + .init_req( init_req6 ), + .init_ack( init_ack6 ) + ); +`endif + +`ifdef MC_HAVE_CS7 +mc_cs_rf #(3'h7) u7( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc7 ), + .tms( tms7 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs7 ), + .wp_err( wp_err7 ), + .lmr_req( lmr_req7 ), + .lmr_ack( lmr_ack7 ), + .init_req( init_req7 ), + .init_ack( init_ack7 ) + ); +`else +mc_cs_rf_dummy #(3'h7) u7( + .clk( clk ), + .rst( rst ), + .wb_we_i( wb_we_i ), + .din( wb_data_i ), + .rf_we( rf_we ), + .addr( wb_addr_i ), + .csc( csc7 ), + .tms( tms7 ), + .poc( poc ), + .csc_mask( csc_mask ), + .cs( cs7 ), + .wp_err( wp_err7 ), + .lmr_req( lmr_req7 ), + .lmr_ack( lmr_ack7 ), + .init_req( init_req7 ), + .init_ack( init_ack7 ) + ); +`endif + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v new file mode 100644 index 000000000..e3a61c42f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v @@ -0,0 +1,1735 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Main Timing Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_timing.v,v 1.8 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.8 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_timing.v,v $ +// Revision 1.8 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.7 2001/12/21 05:09:30 rudi +// +// - Fixed combinatorial loops in synthesis +// - Fixed byte select bug +// +// Revision 1.6 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.5 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.4 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.3 2001/09/02 02:28:28 rudi +// +// Many fixes for minor bugs that showed up in gate level simulations. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.4 2001/06/14 01:57:37 rudi +// +// +// Fixed a potential bug in a corner case situation where the TMS register +// does not propegate properly during initialisation. +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:44 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_timing(clk, rst, + + // Wishbone Interface + wb_cyc_i, wb_stb_i, wb_we_i, + wb_read_go, wb_write_go, wb_first, wb_wait, mem_ack, + err, + + // Suspend/Resume Interface + susp_req, resume_req, suspended, susp_sel, + + // Memory Interface + mc_clk, data_oe, oe_, we_, cas_, ras_, cke_, + cs_en, wb_cycle, wr_cycle, + mc_br, mc_bg, mc_adsc, mc_adv, + mc_c_oe, mc_ack, + not_mem_cyc, + + // Register File Interface + csc, tms, cs, lmr_req, lmr_ack, cs_le_d, cs_le, + + // Address Select Signals + cmd_a10, row_sel, next_adr, page_size, + + // OBCT Signals + bank_set, bank_clr, bank_clr_all, bank_open, any_bank_open, row_same, + + // Data path Controller Signals + dv, pack_le0, pack_le1, pack_le2, par_err, + + // Refresh Counter Signals + rfr_req, rfr_ack, + + // Initialize Request & Ack + init_req, init_ack + ); + +input clk; +input rst; + +// Wishbone Interface +input wb_cyc_i, wb_stb_i, wb_we_i; +input wb_read_go; +input wb_write_go; +input wb_first; +input wb_wait; +output mem_ack; +output err; + +// Suspend/Resume Interface +input susp_req; +input resume_req; +output suspended; +output susp_sel; + +// Memory Interface +input mc_clk; +output data_oe; +output oe_; +output we_; +output cas_; +output ras_; +output cke_; +output cs_en; +output wb_cycle; +output wr_cycle; +input mc_br; +output mc_bg; +output mc_adsc; +output mc_adv; +output mc_c_oe; +input mc_ack; +input not_mem_cyc; + +// Register File Interface +input [31:0] csc; +input [31:0] tms; +input [7:0] cs; +input lmr_req; +output lmr_ack; +output cs_le; +output cs_le_d; + +// Address Select Signals +input [10:0] page_size; +output cmd_a10; +output row_sel; +output next_adr; + +// OBCT Signals +output bank_set; +output bank_clr; +output bank_clr_all; +input bank_open; +input any_bank_open; +input row_same; + +// Data path Controller Signals +output dv; +output pack_le0, pack_le1, pack_le2; // Pack Latch Enable +input par_err; + +// Refresh Counter Signals +input rfr_req; +output rfr_ack; + +// Initialize Request & Ack +input init_req; +output init_ack; + +//////////////////////////////////////////////////////////////////// +// +// Defines & Parameters +// + +// Number of states: 66 +parameter [65:0] // synopsys enum state +// 6666666555555555544444444443333333333222222222211111111110000000000 +// 6543210987654321098765432109876543210987654321098765432109876543210 +POR = 66'b000000000000000000000000000000000000000000000000000000000000000001, +IDLE = 66'b000000000000000000000000000000000000000000000000000000000000000010, +IDLE_T = 66'b000000000000000000000000000000000000000000000000000000000000000100, +IDLE_T2 = 66'b000000000000000000000000000000000000000000000000000000000000001000, +PRECHARGE = 66'b000000000000000000000000000000000000000000000000000000000000010000, +PRECHARGE_W = 66'b000000000000000000000000000000000000000000000000000000000000100000, +ACTIVATE = 66'b000000000000000000000000000000000000000000000000000000000001000000, +ACTIVATE_W = 66'b000000000000000000000000000000000000000000000000000000000010000000, +SD_RD_WR = 66'b000000000000000000000000000000000000000000000000000000000100000000, +SD_RD = 66'b000000000000000000000000000000000000000000000000000000001000000000, +SD_RD_W = 66'b000000000000000000000000000000000000000000000000000000010000000000, +SD_RD_LOOP = 66'b000000000000000000000000000000000000000000000000000000100000000000, +SD_RD_W2 = 66'b000000000000000000000000000000000000000000000000000001000000000000, +SD_WR = 66'b000000000000000000000000000000000000000000000000000010000000000000, +SD_WR_W = 66'b000000000000000000000000000000000000000000000000000100000000000000, +BT = 66'b000000000000000000000000000000000000000000000000001000000000000000, +BT_W = 66'b000000000000000000000000000000000000000000000000010000000000000000, +REFR = 66'b000000000000000000000000000000000000000000000000100000000000000000, +LMR0 = 66'b000000000000000000000000000000000000000000000001000000000000000000, +LMR1 = 66'b000000000000000000000000000000000000000000000010000000000000000000, +LMR2 = 66'b000000000000000000000000000000000000000000000100000000000000000000, +// 6666666555555555544444444443333333333222222222211111111110000000000 +// 6543210987654321098765432109876543210987654321098765432109876543210 +INIT0 = 66'b000000000000000000000000000000000000000000001000000000000000000000, +INIT = 66'b000000000000000000000000000000000000000000010000000000000000000000, +INIT_W = 66'b000000000000000000000000000000000000000000100000000000000000000000, +INIT_REFR1 = 66'b000000000000000000000000000000000000000001000000000000000000000000, +INIT_REFR1_W = 66'b000000000000000000000000000000000000000010000000000000000000000000, +// 6666666555555555544444444443333333333222222222211111111110000000000 +// 6543210987654321098765432109876543210987654321098765432109876543210 +INIT_LMR = 66'b000000000000000000000000000000000000000100000000000000000000000000, +SUSP1 = 66'b000000000000000000000000000000000000001000000000000000000000000000, +SUSP2 = 66'b000000000000000000000000000000000000010000000000000000000000000000, +SUSP3 = 66'b000000000000000000000000000000000000100000000000000000000000000000, +SUSP4 = 66'b000000000000000000000000000000000001000000000000000000000000000000, +RESUME1 = 66'b000000000000000000000000000000000010000000000000000000000000000000, +RESUME2 = 66'b000000000000000000000000000000000100000000000000000000000000000000, +BG0 = 66'b000000000000000000000000000000001000000000000000000000000000000000, +BG1 = 66'b000000000000000000000000000000010000000000000000000000000000000000, +BG2 = 66'b000000000000000000000000000000100000000000000000000000000000000000, +ACS_RD = 66'b000000000000000000000000000001000000000000000000000000000000000000, +ACS_RD1 = 66'b000000000000000000000000000010000000000000000000000000000000000000, +ACS_RD2A = 66'b000000000000000000000000000100000000000000000000000000000000000000, +ACS_RD2 = 66'b000000000000000000000000001000000000000000000000000000000000000000, +ACS_RD3 = 66'b000000000000000000000000010000000000000000000000000000000000000000, +ACS_RD_8_1 = 66'b000000000000000000000000100000000000000000000000000000000000000000, +ACS_RD_8_2 = 66'b000000000000000000000001000000000000000000000000000000000000000000, +ACS_RD_8_3 = 66'b000000000000000000000010000000000000000000000000000000000000000000, +ACS_RD_8_4 = 66'b000000000000000000000100000000000000000000000000000000000000000000, +ACS_RD_8_5 = 66'b000000000000000000001000000000000000000000000000000000000000000000, +ACS_RD_8_6 = 66'b000000000000000000010000000000000000000000000000000000000000000000, +ACS_WR = 66'b000000000000000000100000000000000000000000000000000000000000000000, +ACS_WR1 = 66'b000000000000000001000000000000000000000000000000000000000000000000, +ACS_WR2 = 66'b000000000000000010000000000000000000000000000000000000000000000000, +ACS_WR3 = 66'b000000000000000100000000000000000000000000000000000000000000000000, +ACS_WR4 = 66'b000000000000001000000000000000000000000000000000000000000000000000, +SRAM_RD = 66'b000000000000010000000000000000000000000000000000000000000000000000, +SRAM_RD0 = 66'b000000000000100000000000000000000000000000000000000000000000000000, +SRAM_RD1 = 66'b000000000001000000000000000000000000000000000000000000000000000000, +SRAM_RD2 = 66'b000000000010000000000000000000000000000000000000000000000000000000, +SRAM_RD3 = 66'b000000000100000000000000000000000000000000000000000000000000000000, +SRAM_RD4 = 66'b000000001000000000000000000000000000000000000000000000000000000000, +SRAM_WR = 66'b000000010000000000000000000000000000000000000000000000000000000000, +SRAM_WR0 = 66'b000000100000000000000000000000000000000000000000000000000000000000, +SCS_RD = 66'b000001000000000000000000000000000000000000000000000000000000000000, +SCS_RD1 = 66'b000010000000000000000000000000000000000000000000000000000000000000, +SCS_RD2 = 66'b000100000000000000000000000000000000000000000000000000000000000000, +SCS_WR = 66'b001000000000000000000000000000000000000000000000000000000000000000, +SCS_WR1 = 66'b010000000000000000000000000000000000000000000000000000000000000000, +SCS_ERR = 66'b100000000000000000000000000000000000000000000000000000000000000000; + +//////////////////////////////////////////////////////////////////// +// +// Local Registers & Wires +// + +reg [65:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg mc_bg; + +wire [2:0] mem_type; +wire [1:0] bus_width; +wire kro; + +wire cs_a; +reg [3:0] cmd; + +wire mem_ack; +wire mem_ack_s; +reg mem_ack_d; +reg err_d; +wire err; +reg cmd_a10; +reg lmr_ack; +reg lmr_ack_d; +reg row_sel; +reg oe_; +reg oe_d; +reg data_oe; +reg data_oe_d; +reg cke_d; +reg cke_; +reg init_ack; +reg dv; +reg rfr_ack_d; +reg mc_adsc; +reg mc_adv; + +reg bank_set; +reg bank_clr; +reg bank_clr_all; + +reg wr_set, wr_clr; +reg wr_cycle; + +reg cmd_asserted; +reg cmd_asserted2; + +reg [10:0] burst_val; +reg [10:0] burst_cnt; +wire burst_act; +reg burst_act_rd; +wire single_write; + +reg cs_le_d; +reg cs_le; +reg cs_le_r; + +reg susp_req_r; +reg resume_req_r; +reg suspended; +reg suspended_d; +reg susp_sel_set, susp_sel_clr, susp_sel_r; + +reg [3:0] cmd_del; +reg [3:0] cmd_r; +reg data_oe_r; +reg data_oe_r2; +reg cke_r; +reg cke_rd; +reg cke_o_del; +reg cke_o_r1; +reg cke_o_r2; +reg wb_cycle_set, wb_cycle; +reg [3:0] ack_cnt; +wire ack_cnt_is_0; +reg cnt, cnt_next; +reg [7:0] timer; +reg tmr_ld_trp, tmr_ld_trcd, tmr_ld_tcl, tmr_ld_trfc; +reg tmr_ld_twr, tmr_ld_txsr; +reg tmr2_ld_tscsto; +reg tmr_ld_trdv; +reg tmr_ld_trdz; +reg tmr_ld_twr2; +wire timer_is_zero; +reg tmr_done; +reg tmr2_ld_trdv, tmr2_ld_trdz; +reg tmr2_ld_twpw, tmr2_ld_twd, tmr2_ld_twwd; +reg tmr2_ld_tsrdv; +reg [8:0] timer2; +reg tmr2_done; +wire timer2_is_zero; +reg [3:0] ir_cnt; +reg ir_cnt_ld; +reg ir_cnt_dec; +reg ir_cnt_done; +reg rfr_ack_r; +reg burst_cnt_ld; +reg burst_fp; +reg wb_wait_r, wb_wait_r2; +reg lookup_ready1, lookup_ready2; +reg burst_cnt_ld_4; +reg dv_r; +reg mc_adv_r1, mc_adv_r; + +reg next_adr; +reg pack_le0, pack_le1, pack_le2; +reg pack_le0_d, pack_le1_d, pack_le2_d; +wire bw8, bw16; + +reg mc_c_oe_d; +reg mc_c_oe; + +reg mc_le; +reg mem_ack_r; + +reg rsts, rsts1; +reg no_wb_cycle; + +wire bc_dec; +reg ap_en; // Auto Precharge Enable +reg cmd_a10_r; +reg wb_stb_first; +reg tmr_ld_tavav; + +//////////////////////////////////////////////////////////////////// +// +// Aliases +// +assign mem_type = csc[3:1]; +assign bus_width = csc[5:4]; +assign kro = csc[10]; +assign single_write = tms[9] | (tms[2:0] == 3'h0); + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// +reg cs_le_r1; + +always @(posedge clk) + lmr_ack <= #1 lmr_ack_d; + +assign rfr_ack = rfr_ack_r; + +always @(posedge clk) + cs_le_r <= #1 cs_le_r1; + +always @(posedge clk) + cs_le_r1 <= #1 cs_le; + +always @(posedge clk) + cs_le <= #1 cs_le_d; + +always @(posedge mc_clk or posedge rst) + if(rst) rsts1 <= #1 1'b1; + else rsts1 <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) rsts <= #1 1'b1; + else rsts <= #1 rsts1; + +// Control Signals Output Enable +always @(posedge clk or posedge rst) + if(rst) mc_c_oe <= #1 1'b0; + else mc_c_oe <= #1 mc_c_oe_d; + +always @(posedge clk or posedge rsts) + if(rsts) mc_le <= #1 1'b0; + else mc_le <= #1 ~mc_le; + +always @(posedge clk) + pack_le0 <= #1 pack_le0_d; + +always @(posedge clk) + pack_le1 <= #1 pack_le1_d; + +always @(posedge clk) + pack_le2 <= #1 pack_le2_d; + +always @(posedge clk or posedge rst) + if(rst) mc_adv_r1 <= #1 1'b0; + else + if(!mc_le) mc_adv_r1 <= #1 mc_adv; + +always @(posedge clk or posedge rst) + if(rst) mc_adv_r <= #1 1'b0; + else + if(!mc_le) mc_adv_r <= #1 mc_adv_r1; + +// Bus Width decoder +assign bw8 = (bus_width == `MC_BW_8); +assign bw16 = (bus_width == `MC_BW_16); + +// Any Chip Select +assign cs_a = |cs; + +// Memory to Wishbone Ack +assign mem_ack = (mem_ack_d | mem_ack_s) & (wb_read_go | wb_write_go); + +always @(posedge clk or posedge rst) + if(rst) mem_ack_r <= #1 1'b0; + else mem_ack_r <= #1 mem_ack; + +assign err = err_d; + +// SDRAM Command, either delayed (for writes) or straight through +always @(posedge clk or posedge rst) + if(rst) cmd_r <= #1 `MC_CMD_NOP; + else cmd_r <= #1 cmd; + +always @(posedge clk or posedge rst) + if(rst) cmd_del <= #1 `MC_CMD_NOP; + else cmd_del <= #1 cmd_r; + +assign {cs_en, ras_, cas_, we_} = wr_cycle ? cmd_del : cmd; + +// Track Timing of Asserting a command +always @(posedge clk or posedge rst) + if(rst) cmd_asserted <= #1 1'b0; + else + if(!mc_le) cmd_asserted <= #1 cmd[3]; + +always @(posedge clk or posedge rst) + if(rst) cmd_asserted2 <= #1 1'b0; + else + if(!mc_le) cmd_asserted2 <= #1 cmd_asserted; + +// Output Enable +always @(posedge clk or posedge rst) + if(rst) oe_ <= #1 1'b1; + else oe_ <= #1 ~oe_d; + +// Memory Bus Data lines Output Enable +always @(posedge clk or posedge rst) + if(rst) data_oe_r <= #1 1'b0; + else data_oe_r <= #1 data_oe_d; + +always @(posedge clk or posedge rst) + if(rst) data_oe_r2 <= #1 1'b0; + else data_oe_r2 <= #1 data_oe_r; + +always @(posedge clk or posedge rst) + if(rst) data_oe <= #1 1'b0; + else data_oe <= #1 wr_cycle ? data_oe_r2 : data_oe_d; + +// Clock Enable +always @(posedge clk) + cke_r <= #1 cke_d; + +always @(posedge clk) + cke_ <= #1 cke_r & cke_rd; + +// CKE output delay line to time DV for reads +always @(posedge clk) + cke_o_r1 <= #1 cke_; + +always @(posedge clk) + cke_o_r2 <= #1 cke_o_r1; + +always @(posedge clk) + cke_o_del <= #1 cke_o_r2; + +// Delayed version of the wb_wait input +always @(posedge clk) + wb_wait_r2 <= #1 wb_wait; + +always @(posedge clk) + wb_wait_r <= #1 wb_wait_r2; + +// Indicates when the row_same and bank_open lookups are done +reg lookup_ready1a; + +always @(posedge clk or posedge rst) + if(rst) lookup_ready1 <= #1 1'b0; + else lookup_ready1 <= #1 cs_le & wb_cyc_i & wb_stb_i; + +always @(posedge clk or posedge rst) + if(rst) lookup_ready2 <= #1 1'b0; + else lookup_ready2 <= #1 lookup_ready1 & wb_cyc_i & wb_stb_i; + +// Keep Track if it is a SDRAM write cycle +always @(posedge clk or posedge rst) + if(rst) wr_cycle <= #1 1'b0; + else + if(wr_set) wr_cycle <= #1 1'b1; + else + if(wr_clr) wr_cycle <= #1 1'b0; + +// Track when a cycle is *still* active +always @(posedge clk or posedge rst) + if(rst) wb_cycle <= #1 1'b0; + else + if(wb_cycle_set) wb_cycle <= #1 1'b1; + else + if(!wb_cyc_i | not_mem_cyc) wb_cycle <= #1 1'b0; + +// Thses two signals are used to signal that no wishbone cycle is in +// progress. Need to register them to avoid a very long combinatorial +// path .... +always @(posedge clk or posedge rst) + if(rst) no_wb_cycle <= #1 1'b0; + else no_wb_cycle <= #1 !wb_read_go & !wb_write_go; + +// Track ack's for read cycles +always @(posedge clk or posedge rst) + if(rst) ack_cnt <= #1 4'h0; + else + if(no_wb_cycle) ack_cnt <= #1 4'h0; + else + if(dv & !mem_ack_s) ack_cnt <= #1 ack_cnt + 4'h1; + else + if(!dv & mem_ack_s) ack_cnt <= #1 ack_cnt - 4'h1; + +assign ack_cnt_is_0 = (ack_cnt==4'h0); + +assign mem_ack_s = (ack_cnt != 4'h0) & !wb_wait & !mem_ack_r & wb_read_go & !(wb_we_i & wb_stb_i); + +// Internal Cycle Tracker +always @(posedge clk) + cnt <= #1 cnt_next; + +// Suspend/resume Logic +always @(posedge clk or posedge rst) + if(rst) susp_req_r <= #1 1'b0; + else susp_req_r <= #1 susp_req; + +always @(posedge clk or posedge rst) + if(rst) resume_req_r <= #1 1'b0; + else resume_req_r <= #1 resume_req; + +always @(posedge clk or posedge rst) + if(rst) suspended <= #1 1'b0; + else suspended <= #1 suspended_d; + +always @(posedge clk or posedge rst) + if(rst) rfr_ack_r <= #1 1'b0; + else rfr_ack_r <= #1 rfr_ack_d; + +// Suspend Select Logic +assign susp_sel = susp_sel_r; + +always @(posedge clk or posedge rst) + if(rst) susp_sel_r <= #1 1'b0; + else + if(susp_sel_set) susp_sel_r <= #1 1'b1; + else + if(susp_sel_clr) susp_sel_r <= #1 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// Timing Logic +// +wire [3:0] twrp; +wire twd_is_zero; +wire [31:0] tms_x; + +// FIX_ME +// Hard wire worst case or make it programmable ??? +assign tms_x = (rfr_ack_d | rfr_ack_r | susp_sel | !mc_c_oe) ? 32'hffff_ffff : tms; + +always @(posedge clk) + if(tmr2_ld_tscsto) timer2 <= #1 tms_x[24:16]; + else + if(tmr2_ld_tsrdv) timer2 <= #1 9'd4; // SSRAM RD->1st DATA VALID + else + if(tmr2_ld_twpw) timer2 <= #1 { 5'h0, tms_x[15:12]}; + else + if(tmr2_ld_twd) timer2 <= #1 { 4'h0, tms_x[19:16],1'b0}; + else + if(tmr2_ld_twwd) timer2 <= #1 { 3'h0, tms_x[25:20]}; + else + if(tmr2_ld_trdz) timer2 <= #1 { 4'h0, tms_x[11:8], 1'b1}; + else + if(tmr2_ld_trdv) timer2 <= #1 { tms_x[7:0], 1'b1}; + else + if(!timer2_is_zero) timer2 <= #1 timer2 - 9'b1; + +assign twd_is_zero = (tms_x[19:16] == 4'h0); + +assign timer2_is_zero = (timer2 == 9'h0); + +always @(posedge clk or posedge rst) + if(rst) tmr2_done <= #1 1'b0; + else tmr2_done <= #1 timer2_is_zero & !tmr2_ld_trdv & !tmr2_ld_trdz & + !tmr2_ld_twpw & !tmr2_ld_twd & !tmr2_ld_twwd & !tmr2_ld_tscsto; + +assign twrp = {2'h0,tms_x[16:15]} + tms_x[23:20]; + +// SDRAM Memories timing tracker +always @(posedge clk or posedge rst) +`ifdef MC_POR_DELAY + if(rst) timer <= #1 `MC_POR_DELAY_VAL ; + else +`endif + if(tmr_ld_twr2) timer <= #1 { 4'h0, tms_x[15:12] }; + else + if(tmr_ld_trdz) timer <= #1 { 4'h0, tms_x[11:8] }; + else + if(tmr_ld_trdv) timer <= #1 tms_x[7:0]; + else + if(tmr_ld_twr) timer <= #1 { 4'h0, twrp}; + else + if(tmr_ld_trp) timer <= #1 { 4'h0, tms_x[23:20]}; + else + if(tmr_ld_trcd) timer <= #1 { 5'h0, tms_x[19:17]}; + else + if(tmr_ld_tcl) timer <= #1 { 6'h0, tms_x[05:04]}; + else + if(tmr_ld_trfc) timer <= #1 { 4'h0, tms_x[27:24]}; + else + if(tmr_ld_tavav) timer <= #1 8'h3; + else + if(tmr_ld_txsr) timer <= #1 8'h7; + else + if(!timer_is_zero & !mc_le) timer <= #1 timer - 8'b1; + +assign timer_is_zero = (timer == 8'h0); + +always @(posedge clk or posedge rst) + if(rst) tmr_done <= #1 1'b0; + else tmr_done <= #1 timer_is_zero; + +// Init Refresh Cycles Counter +always @(posedge clk) + if(ir_cnt_ld) ir_cnt <= #1 `MC_INIT_RFRC_CNT; + else + if(ir_cnt_dec) ir_cnt <= #1 ir_cnt - 4'b1; + +always @(posedge clk) + ir_cnt_done <= #1 (ir_cnt == 4'h0); + +// Burst Counter +always @(tms_x or page_size) + case(tms_x[2:0]) // synopsys full_case parallel_case + 3'h0: burst_val = 11'h1; + 3'h1: burst_val = 11'h2; + 3'h2: burst_val = 11'h4; + 3'h3: burst_val = 11'h8; + 3'h7: burst_val = page_size; + endcase + +assign bc_dec = wr_cycle ? mem_ack_d : dv; + +always @(posedge clk) + if(burst_cnt_ld_4) burst_cnt <= #1 11'h4; // for SSRAM only + else + if(burst_cnt_ld) burst_cnt <= #1 burst_val; + else + if(bc_dec) burst_cnt <= #1 burst_cnt - 11'h1; + +always @(posedge clk or posedge rst) + if(rst) burst_fp <= #1 1'b0; + else + if(burst_cnt_ld) burst_fp <= #1 (tms_x[2:0] == 3'h7); + +// Auto Precharge Enable +always @(posedge clk or posedge rst) + if(rst) ap_en <= #1 1'b0; + else + if(burst_cnt_ld) ap_en <= #1 (tms_x[2:0] == 3'h0) & !kro; + +assign burst_act = |burst_cnt & ( |tms_x[2:0] ); + +always @(posedge clk) + burst_act_rd <= #1 |burst_cnt; + +always @(posedge clk or posedge rst) + if(rst) dv_r <= #1 1'b0; + else dv_r <= #1 dv; + +always @(posedge clk) // Auto Precharge Holding Register + cmd_a10_r <= #1 cmd_a10; + +//////////////////////////////////////////////////////////////////// +// +// Main State Machine +// +reg wb_write_go_r; + +always @(posedge clk) + wb_write_go_r <= #1 wb_write_go; + +always @(posedge clk or posedge rst) + if(rst) wb_stb_first <= #1 1'b0; + else + if(mem_ack) wb_stb_first <= #1 1'b0; + else + if(wb_first & wb_stb_i) wb_stb_first <= #1 1'b1; + +always @(posedge clk or posedge rst) +`ifdef MC_POR_DELAY + if(rst) state <= #1 POR; +`else + if(rst) state <= #1 IDLE; +`endif + else state <= #1 next_state; + +always @(state or cs_a or cs_le or cs_le_r or + twd_is_zero or wb_stb_i or wb_write_go_r or + wb_first or wb_read_go or wb_write_go or wb_wait or mem_ack_r or wb_we_i or + ack_cnt_is_0 or wb_wait_r or cnt or wb_cycle or wr_cycle or + mem_type or kro or lookup_ready2 or row_same or cmd_a10_r or + bank_open or single_write or + cmd_asserted or tmr_done or tmr2_done or ir_cnt_done or cmd_asserted2 or + burst_act or burst_act_rd or burst_fp or cke_ or cke_r or cke_o_del or + rfr_req or lmr_req or init_req or rfr_ack_r or susp_req_r or resume_req_r or + mc_br or bw8 or bw16 or dv_r or mc_adv_r or mc_ack or wb_stb_first or ap_en + ) + begin + next_state = state; // Default keep current state + cnt_next = 1'b0; + + cmd = `MC_CMD_NOP; + cmd_a10 = ap_en; + oe_d = 1'b0; + data_oe_d = 1'b0; + cke_d = 1'b1; + cke_rd = 1'b1; + mc_adsc = 1'b0; + mc_adv = 1'b0; + + bank_set = 1'b0; + bank_clr = 1'b0; + bank_clr_all = 1'b0; + + burst_cnt_ld = 1'b0; + burst_cnt_ld_4 = 1'b0; + tmr_ld_trp = 1'b0; + tmr_ld_trcd = 1'b0; + tmr_ld_tcl = 1'b0; + tmr_ld_trfc = 1'b0; + tmr_ld_twr = 1'b0; + tmr_ld_txsr = 1'b0; + tmr_ld_trdv = 1'b0; + tmr_ld_trdz = 1'b0; + tmr_ld_twr2 = 1'b0; + tmr_ld_tavav = 1'b0; + + tmr2_ld_trdv = 1'b0; + tmr2_ld_trdz = 1'b0; + + tmr2_ld_twpw = 1'b0; + tmr2_ld_twd = 1'b0; + tmr2_ld_twwd = 1'b0; + tmr2_ld_tsrdv = 1'b0; + tmr2_ld_tscsto = 1'b0; + + mem_ack_d = 1'b0; + err_d = 1'b0; + rfr_ack_d = 1'b0; + lmr_ack_d = 1'b0; + init_ack = 1'b0; + + ir_cnt_dec = 1'b0; + ir_cnt_ld = 1'b0; + + row_sel = 1'b0; + cs_le_d = 1'b0; + wr_clr = 1'b0; + wr_set = 1'b0; + wb_cycle_set = 1'b0; + dv = 1'b0; + + suspended_d = 1'b0; + susp_sel_set = 1'b0; + susp_sel_clr = 1'b0; + mc_bg = 1'b0; + + next_adr = 1'b0; + pack_le0_d = 1'b0; + pack_le1_d = 1'b0; + pack_le2_d = 1'b0; + + mc_c_oe_d = 1'b1; + + case(state) // synopsys full_case parallel_case +`ifdef MC_POR_DELAY + POR: + begin + if(tmr_done) next_state = IDLE; + end +`endif + IDLE: + begin + //cs_le_d = wb_stb_first | lmr_req; + cs_le_d = wb_stb_first; + + burst_cnt_ld = 1'b1; + wr_clr = 1'b1; + + if(mem_type == `MC_MEM_TYPE_SCS) tmr2_ld_tscsto = 1'b1; + if(mem_type == `MC_MEM_TYPE_SRAM) tmr2_ld_tsrdv = 1'b1; + + if(rfr_req) + begin + rfr_ack_d = 1'b1; + next_state = PRECHARGE; + end + else + if(init_req) + begin + cs_le_d = 1'b1; + next_state = INIT0; + end + else + if(lmr_req & lookup_ready2) + begin + lmr_ack_d = 1'b1; + cs_le_d = 1'b1; + next_state = LMR0; + end + else + if(susp_req_r & !wb_cycle) + begin + cs_le_d = 1'b1; + susp_sel_set = 1'b1; + next_state = SUSP1; + end + else + if(cs_a & (wb_read_go | wb_write_go) & lookup_ready2) + begin + wb_cycle_set = 1'b1; + case(mem_type) // synopsys full_case parallel_case + `MC_MEM_TYPE_SDRAM: // SDRAM + if((lookup_ready2) & !wb_wait) + begin + if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1; + if(kro & bank_open & row_same) next_state = SD_RD_WR; + else + if(kro & bank_open) next_state = PRECHARGE; + else next_state = ACTIVATE; + end + `MC_MEM_TYPE_ACS: + begin // Async Chip Select + if(!wb_wait) + begin + cs_le_d = 1'b1; + if(wb_write_go) + begin + data_oe_d = 1'b1; + next_state = ACS_WR; + end + else next_state = ACS_RD; + end + end + `MC_MEM_TYPE_SCS: + begin // Sync Chip Select + if(!wb_wait) + begin + cs_le_d = 1'b1; + if(wb_write_go) + begin + cmd = `MC_CMD_XWR; + data_oe_d = 1'b1; + tmr_ld_twr2 = 1'b1; + next_state = SCS_WR; + end + else + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr_ld_trdv = 1'b1; + next_state = SCS_RD; + end + end + end + `MC_MEM_TYPE_SRAM: + begin // SRAM + if(!wb_wait) + begin + cs_le_d = 1'b1; + if(wb_write_go) + begin + data_oe_d = 1'b1; + mem_ack_d = 1'b1; + next_state = SRAM_WR; + end + else + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + mc_adsc = 1'b1; + next_state = SRAM_RD; + end + end + end + endcase + end + else + if(mc_br) + begin + if(!cmd_asserted2) + begin + next_state = BG0; + mc_c_oe_d = 1'b0; + end + end + end + + IDLE_T: + begin + cmd_a10 = cmd_a10_r; // Hold Auto Precharge 'til cycle finishes + if(tmr_done & wb_cycle & !wb_wait) cs_le_d = 1'b1; + if(tmr_done) next_state = IDLE; + end + + IDLE_T2: + begin + if(tmr2_done & (!wb_wait | !wb_cycle) ) + begin + cs_le_d = wb_cycle; + if(cs_le_r | !wb_cycle) next_state = IDLE; + end + end + + ///////////////////////////////////////// + // SCS STATES .... + ///////////////////////////////////////// + SCS_RD: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr_ld_trdv = 1'b1; + if(mc_ack) next_state = SCS_RD1; + else + if(tmr2_done) next_state = SCS_ERR; + end + + SCS_RD1: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + if(tmr_done) + begin + mem_ack_d = 1'b1; + tmr_ld_trdz = 1'b1; + next_state = SCS_RD2; + end + end + + SCS_RD2: + begin + tmr_ld_trdz = 1'b1; + next_state = IDLE_T; + end + + SCS_WR: + begin + tmr_ld_twr2 = 1'b1; + cmd = `MC_CMD_XWR; + data_oe_d = 1'b1; + if(mc_ack) next_state = SCS_WR1; + else + if(tmr2_done) next_state = SCS_ERR; + end + + SCS_WR1: + begin + data_oe_d = 1'b1; + if(tmr_done) + begin + mem_ack_d = 1'b1; + next_state = IDLE_T; + end + else cmd = `MC_CMD_XWR; + end + + SCS_ERR: + begin + mem_ack_d = 1'b1; + err_d = 1'b1; + next_state = IDLE_T2; + end + + ///////////////////////////////////////// + // SSRAM STATES .... + ///////////////////////////////////////// + SRAM_RD: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + mc_adsc = 1'b1; + tmr2_ld_tsrdv = 1'b1; + burst_cnt_ld_4 = 1'b1; + if(cmd_asserted) next_state = SRAM_RD0; + end + + SRAM_RD0: + begin + mc_adv = 1'b1; + oe_d = 1'b1; + if(tmr2_done) + begin + mc_adv = !wb_wait; + next_state = SRAM_RD1; + end + end + + SRAM_RD1: + begin + if(mc_adv_r) dv = ~dv_r; + mc_adv = !wb_wait; + + if(!burst_act | !wb_read_go) next_state = SRAM_RD2; + else oe_d = 1'b1; + end + + SRAM_RD2: + begin + if(ack_cnt_is_0 & wb_read_go) next_state = SRAM_RD3; + else + if(!wb_read_go) + begin + mc_adsc = 1'b1; + next_state = SRAM_RD4; + end + end + + SRAM_RD3: + begin + if(!wb_read_go) + begin + mc_adsc = 1'b1; + next_state = SRAM_RD4; + end + else + if(!wb_wait) + begin + cs_le_d = 1'b1; + next_state = SRAM_RD; + end + end + + SRAM_RD4: // DESELECT + begin + if(wb_cycle) cs_le_d = 1'b1; // For RMW + mc_adsc = 1'b1; + next_state = IDLE; + end + + SRAM_WR: + begin + cmd = `MC_CMD_XWR; + mc_adsc = 1'b1; + data_oe_d = 1'b1; + if(cmd_asserted) + begin + if(wb_wait) next_state = SRAM_WR0; + else + if(!wb_write_go) + begin + mc_adsc = 1'b1; + next_state = SRAM_RD4; + end + else + begin + data_oe_d = 1'b1; + mem_ack_d = ~mem_ack_r; + end + end + end + + SRAM_WR0: + begin + if(wb_wait) next_state = SRAM_WR0; + else + if(!wb_write_go) + begin + mc_adsc = 1'b1; + next_state = SRAM_RD4; + end + else + begin + data_oe_d = 1'b1; + next_state = SRAM_WR; + end + end + + ///////////////////////////////////////// + // Async Devices STATES .... + ///////////////////////////////////////// + ACS_RD: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr2_ld_trdv = 1'b1; + next_state = ACS_RD1; + end + + ACS_RD1: + begin // 32 bit, 8 bit - first; 16 bit - first + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + if(tmr2_done) + begin + if(bw8 | bw16) next_adr = 1'b1; + if(bw8) next_state = ACS_RD_8_1; + else + if(bw16) next_state = ACS_RD_8_5; + else next_state = ACS_RD2A; + end + end + + ACS_RD_8_1: + begin // 8 bit 2nd byte + pack_le0_d = 1'b1; + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr2_ld_trdv = 1'b1; + next_state = ACS_RD_8_2; + end + + ACS_RD_8_2: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + if(tmr2_done) + begin + next_adr = 1'b1; + next_state = ACS_RD_8_3; + end + end + + ACS_RD_8_3: + begin // 8 bit 3rd byte + pack_le1_d = 1'b1; + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr2_ld_trdv = 1'b1; + next_state = ACS_RD_8_4; + end + + ACS_RD_8_4: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + if(tmr2_done) + begin + next_adr = 1'b1; + next_state = ACS_RD_8_5; + end + end + + ACS_RD_8_5: + begin // 8 bit 4th byte; 16 bit 2nd word + if(bw8) pack_le2_d = 1'b1; + if(bw16) pack_le0_d = 1'b1; + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + tmr2_ld_trdv = 1'b1; + next_state = ACS_RD_8_6; + end + + ACS_RD_8_6: + begin + cmd = `MC_CMD_XRD; + oe_d = 1'b1; + if(tmr2_done) + begin + next_state = ACS_RD2; + end + end + + ACS_RD2A: + begin + oe_d = 1'b1; + cmd = `MC_CMD_XRD; + next_state = ACS_RD2; + end + + ACS_RD2: + begin + cmd = `MC_CMD_XRD; + next_state = ACS_RD3; + end + + ACS_RD3: + begin + mem_ack_d = 1'b1; + tmr2_ld_trdz = 1'b1; + next_state = IDLE_T2; + end + + ACS_WR: + begin + tmr2_ld_twpw = 1'b1; + cmd = `MC_CMD_XWR; + data_oe_d = 1'b1; + next_state = ACS_WR1; + end + + ACS_WR1: + begin + if(!cmd_asserted) tmr2_ld_twpw = 1'b1; + cmd = `MC_CMD_XWR; + data_oe_d = 1'b1; + if(tmr2_done) + begin + tmr2_ld_twd = 1'b1; + next_state = ACS_WR2; + end + end + + ACS_WR2: + begin + if(twd_is_zero) next_state = ACS_WR3; + else + begin + cmd = `MC_CMD_XRD; + data_oe_d = 1'b1; + next_state = ACS_WR3; + end + end + + ACS_WR3: + begin + if(tmr2_done) next_state = ACS_WR4; + else cmd = `MC_CMD_XRD; + end + + ACS_WR4: + begin + tmr2_ld_twwd = 1'b1; + mem_ack_d = 1'b1; + next_state = IDLE_T2; + end + + ///////////////////////////////////////// + // SDRAM STATES .... + ///////////////////////////////////////// + + PRECHARGE: + begin + cmd = `MC_CMD_PC; + if(rfr_ack_r) + begin + rfr_ack_d = 1'b1; + cmd_a10 = `MC_ALL_BANKS; + bank_clr_all = 1'b1; + end + else + begin + bank_clr = 1'b1; + cmd_a10 = `MC_SINGLE_BANK; + end + tmr_ld_trp = 1'b1; + if(cmd_asserted) next_state = PRECHARGE_W; + end + + PRECHARGE_W: + begin + rfr_ack_d = rfr_ack_r; + if(tmr_done) + begin + if(rfr_ack_r) next_state = REFR; + else next_state = ACTIVATE; + end + end + + ACTIVATE: + begin + if(!wb_wait_r) + begin + row_sel = 1'b1; + tmr_ld_trcd = 1'b1; + cmd = `MC_CMD_ACT; + end + if(cmd_asserted) next_state = ACTIVATE_W; + end + + ACTIVATE_W: + begin + row_sel = 1'b1; + if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1; + + if(kro) bank_set = 1'b1; + + if(tmr_done) + begin + if(wb_write_go) + begin + mem_ack_d = ~mem_ack_r; + cmd_a10 = ap_en | (single_write & !kro); + next_state = SD_WR; + end + else + if(!wb_wait_r) next_state = SD_RD; + end + end + + SD_RD_WR: + begin + if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1; + + if(wb_write_go & !wb_wait) + begin // Write + data_oe_d = 1'b1; + mem_ack_d = ~mem_ack_r; + cmd_a10 = ap_en | (single_write & !kro); + next_state = SD_WR; + end + else + if(!wb_wait) + begin // Read + if(kro) + begin + if(!wb_wait_r) next_state = SD_RD; + end + else next_state = SD_RD; + end + end + + SD_WR: // Write Command + begin // Does the first single write + data_oe_d = 1'b1; + tmr_ld_twr = 1'b1; + cnt_next = ~cnt; + cmd = `MC_CMD_WR; + + cmd_a10 = ap_en | (single_write & !kro); + + if(!cnt & wb_cycle & burst_act) cke_d = ~wb_wait; + else cke_d = cke_r; + + if(cmd_asserted) + begin + mem_ack_d = !mem_ack_r & wb_write_go & !wb_wait & wb_cycle & burst_act; + + if(wb_cycle & !burst_act) next_state = IDLE_T; + else + if(wb_write_go) next_state = SD_WR_W; + else + if(burst_act & !single_write) next_state = BT; + else + if(!ap_en) next_state = BT_W; + else next_state = IDLE_T; + end + + end + + SD_WR_W: + begin // Does additional Writes or Times them + tmr_ld_twr = 1'b1; + cnt_next = ~cnt; + + if(single_write & wb_cycle) + begin + cmd = `MC_CMD_WR; + end + cmd_a10 = ap_en | (single_write & !kro); + + data_oe_d = 1'b1; + mem_ack_d = !mem_ack_r & wb_write_go & !wb_wait & wr_cycle & burst_act; + + if(!cnt) cke_d = ~wb_wait; + else cke_d = cke_r; + + if( (single_write & cke_r) | (!single_write & !cnt & !wb_wait) | (!single_write & cnt & cke_r) ) + begin + if(single_write & !wb_cycle) next_state = IDLE_T; + else + if(burst_act & !single_write & !wb_write_go_r) + begin + cmd = `MC_CMD_BT; + next_state = BT; + end + else + if(!burst_act & !ap_en) next_state = BT_W; + else + if(!burst_act) next_state = IDLE_T; + else + if(!wb_write_go_r & wb_read_go) next_state = IDLE_T; // Added for WMR + end + end + + SD_RD: // Read Command + begin + cmd = `MC_CMD_RD; + cmd_a10 = ap_en; + tmr_ld_tcl = 1'b1; + if(cmd_asserted) next_state = SD_RD_W; + end + + SD_RD_W: + begin + if(tmr_done) next_state = SD_RD_LOOP; + end + + SD_RD_LOOP: + begin + cnt_next = ~cnt; + + if(cnt & !(burst_act & !wb_cycle) & burst_act ) cke_rd = !wb_wait; + else cke_rd = cke_; + + if(wb_cycle & !cnt & burst_act_rd & cke_o_del) dv = 1'b1; + + if(wb_cycle & wb_write_go) next_state = BT; + else + if(burst_act & !wb_cycle) next_state = BT; + else + if(!burst_act) next_state = SD_RD_W2; + end + + SD_RD_W2: + begin + if(wb_write_go | ack_cnt_is_0) + begin + if(!ap_en & !kro) next_state = BT_W; + else + if(!wb_wait & !mem_ack_r) next_state = IDLE_T; + end + end + + BT: + begin + cmd = `MC_CMD_BT; + tmr_ld_trp = 1'b1; + if(cmd_asserted) next_state = BT_W; + end + + BT_W: + begin + cmd_a10 = cmd_a10_r; // Hold Auto Precharge 'til cycle finishes + + if(kro & tmr_done) + begin + if(kro & !wb_wait & (wb_read_go | wb_write_go) ) cs_le_d = 1'b1; + next_state = IDLE; + end + else + if(!kro & tmr_done) // Must do a PRECHARGE after Burst Terminate + begin + bank_clr = 1'b1; + cmd = `MC_CMD_PC; + cmd_a10 = `MC_SINGLE_BANK; + tmr_ld_trp = 1'b1; + if(cmd_asserted) next_state = IDLE_T; + end + end + + REFR: // Refresh Cycle + begin + cs_le_d = 1'b1; + cmd = `MC_CMD_ARFR; + tmr_ld_trfc = 1'b1; + rfr_ack_d = 1'b1; + if(cmd_asserted) + begin + susp_sel_clr = 1'b1; + next_state = IDLE_T; + end + end + + LMR0: + begin + lmr_ack_d = 1'b1; + cmd = `MC_CMD_PC; + cmd_a10 = `MC_ALL_BANKS; + bank_clr_all = 1'b1; + tmr_ld_trp = 1'b1; + if(cmd_asserted) next_state = LMR1; + end + + LMR1: + begin + lmr_ack_d = 1'b1; + if(tmr_done) next_state = LMR2; + end + + LMR2: + begin + bank_clr_all = 1'b1; + cmd = `MC_CMD_LMR; + tmr_ld_trfc = 1'b1; + lmr_ack_d = 1'b1; + if(cmd_asserted) next_state = IDLE_T; + end + + INIT0: + begin + cs_le_d = 1'b1; + next_state = INIT; + end + + INIT: // Initialize SDRAMS + begin // PRECHARGE + init_ack = 1'b1; + cmd = `MC_CMD_PC; + cmd_a10 = `MC_ALL_BANKS; + bank_clr_all = 1'b1; + tmr_ld_trp = 1'b1; + ir_cnt_ld = 1'b1; + if(cmd_asserted) next_state = INIT_W; + end + + INIT_W: + begin + init_ack = 1'b1; + if(tmr_done) next_state = INIT_REFR1; + end + + INIT_REFR1: // Init Refresh Cycle 1 + begin + init_ack = 1'b1; + cmd = `MC_CMD_ARFR; + tmr_ld_trfc = 1'b1; + if(cmd_asserted) + begin + ir_cnt_dec = 1'b1; + next_state = INIT_REFR1_W; + end + end + + INIT_REFR1_W: + begin + init_ack = 1'b1; + if(tmr_done) + begin + if(ir_cnt_done) next_state = INIT_LMR; + else next_state = INIT_REFR1; + end + end + + INIT_LMR: + begin + init_ack = 1'b1; + cmd = `MC_CMD_LMR; + bank_clr_all = 1'b1; + tmr_ld_trfc = 1'b1; + if(cmd_asserted) next_state = IDLE_T; + end + + ///////////////////////////////////////// + // Bus Arbitration STATES .... + ///////////////////////////////////////// + BG0: + begin // Bus Grant + mc_bg = 1'b1; + mc_c_oe_d = 1'b0; + next_state = BG1; + end + BG1: + begin // Bus Grant + mc_bg = 1'b1; + cs_le_d = 1'b1; + mc_c_oe_d = 1'b0; + next_state = BG2; + end + BG2: + begin // Bus Grant + cs_le_d = 1'b1; + mc_bg = !wb_read_go & !wb_write_go & + !rfr_req & !init_req & !lmr_req & + !susp_req_r; + tmr_ld_tavav = 1'b1; + mc_c_oe_d = mc_br; + if(!mc_br) next_state = IDLE_T; + end + + ///////////////////////////////////////// + // SUSPEND/RESUME STATES .... + ///////////////////////////////////////// + SUSP1: + begin // Precharge All + cmd = `MC_CMD_PC; + cmd_a10 = `MC_ALL_BANKS; + bank_clr_all = 1'b1; + tmr_ld_trp = 1'b1; + if(cmd_asserted) next_state = SUSP2; + end + + SUSP2: + begin + if(tmr_done) next_state = SUSP3; + end + + SUSP3: + begin // Enter Self refresh Mode + cke_d = 1'b0; + cmd = `MC_CMD_ARFR; + rfr_ack_d = 1'b1; + if(cmd_asserted) + begin + next_state = SUSP4; + end + end + + SUSP4: + begin // Now we are suspended + cke_rd = 1'b0; + suspended_d = 1'b1; + tmr_ld_txsr = 1'b1; + if(resume_req_r) next_state = RESUME1; + end + + RESUME1: + begin + suspended_d = 1'b1; + tmr_ld_txsr = 1'b1; + next_state = RESUME2; + end + + RESUME2: + begin + suspended_d = 1'b1; + if(tmr_done) next_state = REFR; + end + +// synopsys translate_off + default: + $display("MC_TIMING SM: Entered non existing state ... (%t)",$time); +// synopsys translate_on + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v new file mode 100644 index 000000000..3058e287a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v @@ -0,0 +1,549 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_top.v,v 1.7 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.7 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_top.v,v $ +// Revision 1.7 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.6 2001/12/21 05:09:30 rudi +// +// - Fixed combinatorial loops in synthesis +// - Fixed byte select bug +// +// Revision 1.5 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.4 2001/09/10 13:44:17 rudi +// *** empty log message *** +// +// Revision 1.3 2001/09/02 02:28:28 rudi +// +// Many fixes for minor bugs that showed up in gate level simulations. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:39 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_top(clk_i, rst_i, + + wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, + + susp_req_i, resume_req_i, suspended_o, poc_o, + + mc_clk_i, mc_br_pad_i, mc_bg_pad_o, mc_ack_pad_i, + mc_addr_pad_o, mc_data_pad_i, mc_data_pad_o, mc_dp_pad_i, + mc_dp_pad_o, mc_doe_pad_doe_o, mc_dqm_pad_o, mc_oe_pad_o_, + mc_we_pad_o_, mc_cas_pad_o_, mc_ras_pad_o_, mc_cke_pad_o_, + mc_cs_pad_o_, mc_sts_pad_i, mc_rp_pad_o_, mc_vpen_pad_o, + mc_adsc_pad_o_, mc_adv_pad_o_, mc_zz_pad_o, mc_coe_pad_coe_o + ); + +input clk_i, rst_i; + +// -------------------------------------- +// WISHBONE SLAVE INTERFACE +input [31:0] wb_data_i; +output [31:0] wb_data_o; +input [31:0] wb_addr_i; +input [3:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; + +// -------------------------------------- +// Suspend Resume Interface +input susp_req_i; +input resume_req_i; +output suspended_o; + +// POC +output [31:0] poc_o; + +// -------------------------------------- +// Memory Bus Signals +input mc_clk_i; +input mc_br_pad_i; +output mc_bg_pad_o; +input mc_ack_pad_i; +output [23:0] mc_addr_pad_o; +input [31:0] mc_data_pad_i; +output [31:0] mc_data_pad_o; +input [3:0] mc_dp_pad_i; +output [3:0] mc_dp_pad_o; +output mc_doe_pad_doe_o; +output [3:0] mc_dqm_pad_o; +output mc_oe_pad_o_; +output mc_we_pad_o_; +output mc_cas_pad_o_; +output mc_ras_pad_o_; +output mc_cke_pad_o_; +output [7:0] mc_cs_pad_o_; +input mc_sts_pad_i; +output mc_rp_pad_o_; +output mc_vpen_pad_o; +output mc_adsc_pad_o_; +output mc_adv_pad_o_; +output mc_zz_pad_o; +output mc_coe_pad_coe_o; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +// WISHBONE Interface Interconnects +wire wb_read_go; +wire wb_write_go; +wire wb_first; +wire wb_wait; +wire mem_ack; + +// Suspend Resume Interface +wire susp_sel; + +// Register File Interconnects +wire [31:0] rf_dout; +wire [31:0] csc; +wire [31:0] tms; +wire [31:0] sp_csc; +wire [31:0] sp_tms; +wire [7:0] cs; +wire fs; +wire cs_le; +wire [7:0] cs_need_rfr; +wire [2:0] ref_int; +wire [31:0] mem_dout; +wire wp_err; + +// Address Select Signals +wire [12:0] row_adr; +wire [1:0] bank_adr; +wire cmd_a10; +wire row_sel; +wire next_adr; +wire [10:0] page_size; +wire lmr_sel; +wire wr_hold; + +// OBCT Signals +wire bank_set; +wire bank_clr; +wire bank_clr_all; +wire bank_open; +wire row_same; +wire [7:0] obct_cs; +wire any_bank_open; + +// Data path Controller Signals +wire dv; +wire pack_le0, pack_le1, pack_le2; // Pack Latch Enable +wire par_err; +wire [31:0] mc_data_od; +wire [3:0] mc_dp_od; +wire [23:0] mc_addr_d; +wire [35:0] mc_data_ir; + +// Refresh Counter Signals +wire rfr_req; +wire rfr_ack; +wire [7:0] rfr_ps_val; + +// Memory Timing Block Signals +wire data_oe; +wire oe_; +wire we_; +wire cas_; +wire ras_; +wire cke_; +wire lmr_req; +wire lmr_ack; +wire init_req; +wire init_ack; +wire [7:0] spec_req_cs; +wire cs_en; +wire wb_cycle, wr_cycle; +wire [31:0] tms_s; +wire [31:0] csc_s; +wire mc_c_oe_d; +wire mc_br_r; +wire mc_bg_d; +wire mc_adsc_d; +wire mc_adv_d; +wire mc_ack_r; +wire err; +wire mc_sts_i; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign obct_cs = (rfr_ack | susp_sel) ? cs_need_rfr : + (lmr_ack | init_ack) ? spec_req_cs : cs; + +assign lmr_sel = lmr_ack | init_ack; + +assign tms_s = lmr_sel ? sp_tms : tms; +assign csc_s = lmr_sel ? sp_csc : csc; + + +wire not_mem_cyc; + +assign not_mem_cyc = wb_cyc_i & wb_stb_i & !( `MC_MEM_SEL ); + +reg mem_ack_r; + +always @(posedge clk_i) + mem_ack_r <= #1 mem_ack; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +mc_rf u0( + .clk( clk_i ), + .rst( rst_i ), + .wb_data_i( wb_data_i ), + .rf_dout( rf_dout ), + .wb_addr_i( wb_addr_i ), + .wb_we_i( wb_we_i ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_ack_o( ), + .wp_err( wp_err ), + .csc( csc ), + .tms( tms ), + .poc( poc_o ), + .sp_csc( sp_csc ), + .sp_tms( sp_tms ), + .cs( cs ), + .mc_data_i( mc_data_ir[31:0]), + .mc_sts( mc_sts_ir ), + .mc_vpen( mc_vpen_pad_o ), + .fs( fs ), + .cs_le( cs_le ), + .cs_le_d( cs_le_d ), + .cs_need_rfr( cs_need_rfr ), + .ref_int( ref_int ), + .rfr_ps_val( rfr_ps_val ), + .spec_req_cs( spec_req_cs ), + .init_req( init_req ), + .init_ack( init_ack ), + .lmr_req( lmr_req ), + .lmr_ack( lmr_ack ) + ); + +mc_adr_sel u1( + .clk( clk_i ), + .csc( csc_s ), + .tms( tms_s ), + .wb_stb_i( wb_stb_i ), + //.wb_ack_o( wb_ack_o ), + .wb_ack_o( mem_ack_r ), + .wb_addr_i( wb_addr_i ), + .wb_we_i( wb_we_i ), + .wb_write_go( wb_write_go ), + .wr_hold( wr_hold ), + .cas_( cas_ ), + .mc_addr( mc_addr_d ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .rfr_ack( rfr_ack ), + .cs_le( cs_le ), + .cmd_a10( cmd_a10 ), + .row_sel( row_sel ), + .lmr_sel( lmr_sel ), + .next_adr( next_adr ), + .wr_cycle( wr_cycle ), + .page_size( page_size ) + ); + +mc_obct_top u2( + .clk( clk_i ), + .rst( rst_i ), + .cs( obct_cs ), + .row_adr( row_adr ), + .bank_adr( bank_adr ), + .bank_set( bank_set ), + .bank_clr( bank_clr ), + .bank_clr_all( bank_clr_all ), + .bank_open( bank_open ), + .any_bank_open( any_bank_open ), + .row_same( row_same ), + .rfr_ack( rfr_ack ) + ); + +mc_dp u3( + .clk( clk_i ), + .rst( rst_i ), + .csc( csc ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .mem_ack( mem_ack ), + //.wb_ack_o( wb_ack_o ), + .wb_ack_o( mem_ack_r ), + .wb_we_i( wb_we_i ), + .wb_data_i( wb_data_i ), + .wb_data_o( mem_dout ), + .wb_read_go( wb_read_go ), + .mc_clk( mc_clk_i ), + .mc_data_del( mc_data_ir ), + .mc_dp_i( mc_dp_pad_i ), + .mc_data_o( mc_data_od ), + .mc_dp_o( mc_dp_od ), + .dv( dv ), + .pack_le0( pack_le0 ), + .pack_le1( pack_le1 ), + .pack_le2( pack_le2 ), + .byte_en( wb_sel_i ), + .par_err( par_err ) + ); + +mc_refresh u4( + .clk( clk_i ), + .rst( rst_i ), + .cs_need_rfr( cs_need_rfr ), + .ref_int( ref_int ), + .rfr_req( rfr_req ), + .rfr_ack( rfr_ack ), + .rfr_ps_val( rfr_ps_val ) + ); + +mc_timing u5( + .clk( clk_i ), + .mc_clk( mc_clk_i ), + .rst( rst_i ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_we_i( wb_we_i ), + .wb_read_go( wb_read_go ), + .wb_write_go( wb_write_go ), + .wb_first( wb_first ), + .wb_wait( wb_wait ), + .mem_ack( mem_ack ), + .err( err ), + .susp_req( susp_req_i ), + .resume_req( resume_req_i ), + .suspended( suspended_o ), + .susp_sel( susp_sel ), + .mc_br( mc_br_r ), + .mc_bg( mc_bg_d ), + .mc_ack( mc_ack_r ), + .not_mem_cyc( not_mem_cyc ), + .data_oe( data_oe ), + .oe_( oe_ ), + .we_( we_ ), + .cas_( cas_ ), + .ras_( ras_ ), + .cke_( cke_ ), + .cs_en( cs_en ), + .mc_adsc( mc_adsc_d ), + .mc_adv( mc_adv_d ), + .mc_c_oe( mc_c_oe_d ), + .wb_cycle( wb_cycle ), + .wr_cycle( wr_cycle ), + .csc( csc_s ), + .tms( tms_s ), + .cs( obct_cs ), + .lmr_req( lmr_req ), + .lmr_ack( lmr_ack ), + .cs_le( cs_le ), + .cs_le_d( cs_le_d ), + .cmd_a10( cmd_a10 ), + .row_sel( row_sel ), + .next_adr( next_adr ), + .page_size( page_size ), + .bank_set( bank_set ), + .bank_clr( bank_clr ), + .bank_clr_all( bank_clr_all ), + .bank_open( bank_open ), + .any_bank_open( any_bank_open ), + .row_same( row_same ), + .dv( dv ), + .pack_le0( pack_le0 ), + .pack_le1( pack_le1 ), + .pack_le2( pack_le2 ), + .par_err( par_err ), + .rfr_req( rfr_req ), + .rfr_ack( rfr_ack ), + .init_req( init_req ), + .init_ack( init_ack ) + ); + +mc_wb_if u6( + .clk( clk_i ), + .rst( rst_i ), + .wb_addr_i( wb_addr_i ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_we_i( wb_we_i ), + .wb_ack_o( wb_ack_o ), + .wb_err( wb_err_o ), + .wb_read_go( wb_read_go ), + .wb_write_go( wb_write_go ), + .wb_first( wb_first ), + .wb_wait( wb_wait ), + .mem_ack( mem_ack ), + .wr_hold( wr_hold ), + .err( err ), + .par_err( par_err ), + .wp_err( wp_err ), + .wb_data_o( wb_data_o ), + .mem_dout( mem_dout ), + .rf_dout( rf_dout ) + ); + +mc_mem_if u7( + .clk( clk_i ), + .rst( rst_i ), + .mc_rp( mc_rp_pad_o_ ), + .mc_clk( mc_clk_i ), + .mc_br( mc_br_pad_i ), + .mc_bg( mc_bg_pad_o ), + .mc_addr( mc_addr_pad_o ), + .mc_data_o( mc_data_pad_o ), + .mc_dp_o( mc_dp_pad_o ), + .mc_data_oe( mc_doe_pad_doe_o), + .mc_dqm( mc_dqm_pad_o ), + .mc_oe_( mc_oe_pad_o_ ), + .mc_we_( mc_we_pad_o_ ), + .mc_cas_( mc_cas_pad_o_ ), + .mc_ras_( mc_ras_pad_o_ ), + .mc_cke_( mc_cke_pad_o_ ), + .mc_cs_( mc_cs_pad_o_ ), + .mc_adsc_( mc_adsc_pad_o_ ), + .mc_adv_( mc_adv_pad_o_ ), + .mc_br_r( mc_br_r ), + .mc_bg_d( mc_bg_d ), + .mc_data_od( mc_data_od ), + .mc_dp_od( mc_dp_od ), + .mc_addr_d( mc_addr_d ), + .mc_ack( mc_ack_pad_i ), + .mc_zz_o( mc_zz_pad_o ), + .we_( we_ ), + .ras_( ras_ ), + .cas_( cas_ ), + .cke_( cke_ ), + .mc_adsc_d( mc_adsc_d ), + .mc_adv_d( mc_adv_d ), + .cs_en( cs_en ), + .rfr_ack( rfr_ack ), + .cs_need_rfr( cs_need_rfr ), + .lmr_sel( lmr_sel ), + .spec_req_cs( spec_req_cs ), + .cs( cs ), + .fs( fs ), + .data_oe( data_oe ), + .susp_sel( susp_sel ), + .suspended_o( suspended_o ), + .mc_c_oe( mc_coe_pad_coe_o), + .mc_c_oe_d( mc_c_oe_d ), + .mc_ack_r( mc_ack_r ), + .oe_( oe_ ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_sel_i( wb_sel_i ), + .wb_cycle( wb_cycle ), + .wr_cycle( wr_cycle ), + .mc_data_i( mc_data_pad_i ), + .mc_dp_i( mc_dp_pad_i ), + .mc_data_ir( mc_data_ir ), + .mc_sts_i( mc_sts_pad_i ), + .mc_sts_ir( mc_sts_ir ) + ); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v new file mode 100644 index 000000000..3d58f3a89 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v @@ -0,0 +1,252 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Memory Controller //// +//// WISHBONE Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: mc_wb_if.v,v 1.6 2002/01/21 13:08:52 rudi Exp $ +// +// $Date: 2002/01/21 13:08:52 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: mc_wb_if.v,v $ +// Revision 1.6 2002/01/21 13:08:52 rudi +// +// Fixed several minor bugs, cleaned up the code further ... +// +// Revision 1.5 2001/12/11 02:47:19 rudi +// +// - Made some changes not to expect clock during reset ... +// +// Revision 1.4 2001/11/29 02:16:28 rudi +// +// +// - More Synthesis cleanup, mostly for speed +// - Several bug fixes +// - Changed code to avoid auto-precharge and +// burst-terminate combinations (apparently illegal ?) +// Now we will do a manual precharge ... +// +// Revision 1.3 2001/09/24 00:38:21 rudi +// +// Changed Reset to be active high and async. +// +// Revision 1.2 2001/08/10 08:16:21 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Removed "Refresh Early" configuration +// +// Revision 1.1 2001/07/29 07:34:41 rudi +// +// +// 1) Changed Directory Structure +// 2) Fixed several minor bugs +// +// Revision 1.3 2001/06/12 15:19:49 rudi +// +// +// Minor changes after running lint, and a small bug +// fix reading csr and ba_mask registers. +// +// Revision 1.2 2001/06/03 11:37:17 rudi +// +// +// 1) Fixed Chip Select Mask Register +// - Power On Value is now all ones +// - Comparison Logic is now correct +// +// 2) All resets are now asynchronous +// +// 3) Converted Power On Delay to an configurable item +// +// 4) Added reset to Chip Select Output Registers +// +// 5) Forcing all outputs to Hi-Z state during reset +// +// Revision 1.1.1.1 2001/05/13 09:39:47 rudi +// Created Directory Structure +// +// +// +// + +`include "mc_defines.v" + +module mc_wb_if(clk, rst, + wb_addr_i, wb_cyc_i, wb_stb_i, wb_we_i, wb_err, wb_ack_o, + wb_read_go, wb_write_go, + wb_first, wb_wait, mem_ack, wr_hold, + err, par_err, wp_err, + wb_data_o, mem_dout, rf_dout); + +input clk, rst; +input [31:0] wb_addr_i; +input wb_cyc_i; +input wb_stb_i; +input wb_we_i; +output wb_err; +output wb_ack_o; +output wb_read_go; +output wb_write_go; +output wb_first; +output wb_wait; +input mem_ack; +output wr_hold; +input err, par_err, wp_err; +output [31:0] wb_data_o; +input [31:0] mem_dout, rf_dout; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +wire mem_sel; +reg read_go_r; +reg read_go_r1; +reg write_go_r; +reg write_go_r1; +reg wb_first_r; +wire wb_first_set; +reg wr_hold; +wire rmw; +reg rmw_r; +reg rmw_en; +reg wb_ack_o; +reg wb_err; +reg [31:0] wb_data_o; + +//////////////////////////////////////////////////////////////////// +// +// Memory Go Logic +// + +assign mem_sel = `MC_MEM_SEL; + +always @(posedge clk or posedge rst) + if(rst) rmw_en <= #1 1'b0; + else + if(wb_ack_o) rmw_en <= #1 1'b1; + else + if(!wb_cyc_i) rmw_en <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) rmw_r <= #1 1'b0; + else rmw_r <= #1 !wr_hold & wb_we_i & wb_cyc_i & wb_stb_i & rmw_en; + +assign rmw = rmw_r | (!wr_hold & wb_we_i & wb_cyc_i & wb_stb_i & rmw_en); + +always @(posedge clk or posedge rst) + if(rst) read_go_r1 <= #1 1'b0; + else read_go_r1 <= #1 !rmw & wb_cyc_i & + ((wb_stb_i & mem_sel & !wb_we_i) | read_go_r); + +always @(posedge clk or posedge rst) + if(rst) read_go_r <= #1 1'b0; + else read_go_r <= #1 read_go_r1 & wb_cyc_i; + +assign wb_read_go = !rmw & read_go_r1 & wb_cyc_i; + +always @(posedge clk or posedge rst) + if(rst) write_go_r1 <= #1 1'b0; + else write_go_r1 <= #1 wb_cyc_i & + ((wb_stb_i & mem_sel & wb_we_i) | write_go_r); + +always @(posedge clk or posedge rst) + if(rst) write_go_r <= #1 1'b0; + else write_go_r <= #1 write_go_r1 & wb_cyc_i & + ((wb_we_i & wb_stb_i) | !wb_stb_i); + +assign wb_write_go = !rmw & write_go_r1 & wb_cyc_i & + ((wb_we_i & wb_stb_i) | !wb_stb_i); + +assign wb_first_set = mem_sel & wb_cyc_i & wb_stb_i & !(read_go_r | write_go_r); +assign wb_first = wb_first_set | (wb_first_r & !wb_ack_o & !wb_err); + +always @(posedge clk or posedge rst) + if(rst) wb_first_r <= #1 1'b0; + else + if(wb_first_set) wb_first_r <= #1 1'b1; + else + if(wb_ack_o | wb_err) wb_first_r <= #1 1'b0; + +always @(posedge clk or posedge rst) + if(rst) wr_hold <= #1 1'b0; + else + if(wb_cyc_i & wb_stb_i) wr_hold <= #1 wb_we_i; + +//////////////////////////////////////////////////////////////////// +// +// WB Ack +// + +wire wb_err_d; + +// Ack no longer asserted when wb_err is asserted +always @(posedge clk or posedge rst) + if(rst) wb_ack_o <= #1 1'b0; + else wb_ack_o <= #1 `MC_MEM_SEL ? mem_ack & !wb_err_d : + `MC_REG_SEL & wb_cyc_i & wb_stb_i & !wb_ack_o; + +assign wb_err_d = wb_cyc_i & wb_stb_i & (par_err | err | wp_err); + +always @(posedge clk or posedge rst) + if(rst) wb_err <= #1 1'b0; + else wb_err <= #1 `MC_MEM_SEL & wb_err_d & !wb_err; + +//////////////////////////////////////////////////////////////////// +// +// Memory Wait Logic +// + +assign wb_wait = wb_cyc_i & !wb_stb_i & (wb_write_go | wb_read_go); + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Data Output +// + +always @(posedge clk) + wb_data_o <= #1 `MC_MEM_SEL ? mem_dout : rf_dout; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v b/openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v new file mode 100644 index 000000000..b96ac9178 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "bus_commands.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README.pdf //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: bus_commands.v,v $ +// Revision 1.4 2002/08/22 13:28:05 mihad +// Updated for synthesis purposes. Gate level simulation was failing in some configurations +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// definitions of PCI bus commands | used by PCI Master | used by PCI Target +`define BC_IACK 4'h0 // yes no +`define BC_SPECIAL 4'h1 // no no +`define BC_IO_READ 4'h2 // yes yes +`define BC_IO_WRITE 4'h3 // yes yes +`define BC_RESERVED0 4'h4 // no no +`define BC_RESERVED1 4'h5 // no no +`define BC_MEM_READ 4'h6 // yes yes +`define BC_MEM_WRITE 4'h7 // yes yes +`define BC_RESERVED2 4'h8 // no no +`define BC_RESERVED3 4'h9 // no no +`define BC_CONF_READ 4'hA // yes yes +`define BC_CONF_WRITE 4'hB // yes yes +`define BC_MEM_READ_MUL 4'hC // yes yes +`define BC_DUAL_ADDR_CYC 4'hD // no no +`define BC_MEM_READ_LN 4'hE // yes yes +`define BC_MEM_WRITE_INVAL 4'hF // no yes + +// common bits for configuration cycle commands +`define BC_CONF_RW 3'b101 +// common bits for io cycle commands +`define BC_IO_RW 3'b001 diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v new file mode 100644 index 000000000..86027e62f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v @@ -0,0 +1,102 @@ +//=========================================================================== +// $Id: pci_async_reset_flop.v,v 1.1 2003/01/27 16:49:31 mihad Exp $ +// +////////////////////////////////////////////////////////////////////// +//// //// +//// async_reset_flop //// +//// //// +//// This file is part of the general opencores effort. //// +//// //// +//// //// +//// Module Description: //// +//// //// +//// Make a rising-edge triggered flop with async reset with a //// +//// distinguished name so that it's output can be easily //// +//// traced, because it is used for asynchronous reset of some //// +//// flip-flops. //// +//// //// +//// This flop should be used instead of a regular flop for ALL //// +//// asynchronous-reset generator flops. //// +//// //// +//// To Do: //// +//// Nothing //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_async_reset_flop.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/08/14 16:44:19 mihad +// Include statement was enclosed in synosys translate off/on directive - repaired +// +// Revision 1.2 2002/02/25 15:15:43 mihad +// Added include statement that was missing and causing errors +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "pci_constants.v" + +module pci_async_reset_flop ( + data_in, clk_in, async_reset_data_out, reset_in +); + +input data_in; +input clk_in; +output async_reset_data_out; +input reset_in; + +reg async_reset_data_out; + +always @(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + async_reset_data_out <= #`FF_DELAY 1'b0; + end + else + begin + async_reset_data_out <= #`FF_DELAY data_in; + end +end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v new file mode 100644 index 000000000..bba700a8e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v @@ -0,0 +1,1653 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_bridge32.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// - Tadej Markovic (tadej@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_bridge32.v,v $ +// Revision 1.19 2004/09/23 13:48:53 mihad +// The control inputs from PCI are now muxed with control outputs +// using output enable state for given signal. +// +// Revision 1.18 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.17 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.16 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.15 2003/12/10 12:02:54 mihad +// The wbs B3 to B2 translation logic had wrong reset wire connected! +// +// Revision 1.14 2003/12/09 09:33:57 simons +// Some warning cleanup. +// +// Revision 1.13 2003/10/17 09:11:52 markom +// mbist signals updated according to newest convention +// +// Revision 1.12 2003/08/21 20:49:03 tadejm +// Added signals for WB Master B3. +// +// Revision 1.11 2003/08/08 16:36:33 tadejm +// Added 'three_left_out' to pci_pciw_fifo signaling three locations before full. Added comparison between current registered cbe and next unregistered cbe to signal wb_master whether it is allowed to performe burst or not. Due to this, I needed 'three_left_out' so that writing to pci_pciw_fifo can be registered, otherwise timing problems would occure. +// +// Revision 1.10 2003/08/03 18:05:06 mihad +// Added limited WISHBONE B3 support for WISHBONE Slave Unit. +// Doesn't support full speed bursts yet. +// +// Revision 1.9 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.8 2002/10/21 13:04:33 mihad +// Changed BIST signal names etc.. +// +// Revision 1.7 2002/10/18 03:36:37 tadejm +// Changed wrong signal name mbist_sen into mbist_ctrl_i. +// +// Revision 1.6 2002/10/17 22:51:50 tadejm +// Changed BIST signals for RAMs. +// +// Revision 1.5 2002/10/11 10:09:01 mihad +// Added additional testcase and changed rst name in BIST to trst +// +// Revision 1.4 2002/10/08 17:17:05 mihad +// Added BIST signals for RAMs. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// this is top level module of pci bridge core +// it instantiates and connects other lower level modules +// check polarity of PCI output enables in file out_reg.v and change it according to IO interface specification + +module pci_bridge32 +( + // WISHBONE system signals + wb_clk_i, + wb_rst_i, + wb_rst_o, + wb_int_i, + wb_int_o, + + // WISHBONE slave interface + wbs_adr_i, + wbs_dat_i, + wbs_dat_o, + wbs_sel_i, + wbs_cyc_i, + wbs_stb_i, + wbs_we_i, + +`ifdef PCI_WB_REV_B3 + + wbs_cti_i, + wbs_bte_i, + +`else + + wbs_cab_i, + +`endif + + wbs_ack_o, + wbs_rty_o, + wbs_err_o, + + // WISHBONE master interface + wbm_adr_o, + wbm_dat_i, + wbm_dat_o, + wbm_sel_o, + wbm_cyc_o, + wbm_stb_o, + wbm_we_o, + wbm_cti_o, + wbm_bte_o, + wbm_ack_i, + wbm_rty_i, + wbm_err_i, + + // pci interface - system pins + pci_clk_i, + pci_rst_i, + pci_rst_o, + pci_inta_i, + pci_inta_o, + pci_rst_oe_o, + pci_inta_oe_o, + + // arbitration pins + pci_req_o, + pci_req_oe_o, + + pci_gnt_i, + + // protocol pins + pci_frame_i, + pci_frame_o, + + pci_frame_oe_o, + pci_irdy_oe_o, + pci_devsel_oe_o, + pci_trdy_oe_o, + pci_stop_oe_o, + pci_ad_oe_o, + pci_cbe_oe_o, + + pci_irdy_i, + pci_irdy_o, + + pci_idsel_i, + + pci_devsel_i, + pci_devsel_o, + + pci_trdy_i, + pci_trdy_o, + + pci_stop_i, + pci_stop_o , + + // data transfer pins + pci_ad_i, + pci_ad_o, + + pci_cbe_i, + pci_cbe_o, + + // parity generation and checking pins + pci_par_i, + pci_par_o, + pci_par_oe_o, + + pci_perr_i, + pci_perr_o, + pci_perr_oe_o, + + // system error pin + pci_serr_o, + pci_serr_oe_o + +`ifdef PCI_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif + +`ifdef PCI_CPCI_HS_IMPLEMENT + , + // Compact PCI Hot Swap signals + pci_cpci_hs_enum_o , // ENUM# output with output enable (open drain) + pci_cpci_hs_enum_oe_o , // ENUM# enum output enable + pci_cpci_hs_led_o , // LED output with output enable (open drain) + pci_cpci_hs_led_oe_o , // LED output enable + pci_cpci_hs_es_i // ejector switch state indicator input +`endif + +`ifdef PCI_SPOCI + , + // Serial power on configuration interface + spoci_scl_o , + spoci_scl_oe_o , + spoci_sda_i , + spoci_sda_o , + spoci_sda_oe_o +`endif + +); + +`ifdef HOST + `ifdef NO_CNF_IMAGE + parameter pci_ba0_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + `else + parameter pci_ba0_width = 20 ; + `endif +`endif + +`ifdef GUEST + parameter pci_ba0_width = 20 ; +`endif + +parameter pci_ba1_5_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + +// WISHBONE system signals +input wb_clk_i ; +input wb_rst_i ; +output wb_rst_o ; +input wb_int_i ; +output wb_int_o ; + +// WISHBONE slave interface +input [31:0] wbs_adr_i ; +input [31:0] wbs_dat_i ; +output [31:0] wbs_dat_o ; +input [3:0] wbs_sel_i ; +input wbs_cyc_i ; +input wbs_stb_i ; +input wbs_we_i ; + +`ifdef PCI_WB_REV_B3 + +input [2:0] wbs_cti_i ; +input [1:0] wbs_bte_i ; + +`else + +input wbs_cab_i ; + +`endif + +output wbs_ack_o ; +output wbs_rty_o ; +output wbs_err_o ; + +// WISHBONE master interface +output [31:0] wbm_adr_o ; +input [31:0] wbm_dat_i ; +output [31:0] wbm_dat_o ; +output [3:0] wbm_sel_o ; +output wbm_cyc_o ; +output wbm_stb_o ; +output wbm_we_o ; +output [2:0] wbm_cti_o ; +output [1:0] wbm_bte_o ; +input wbm_ack_i ; +input wbm_rty_i ; +input wbm_err_i ; + +// pci interface - system pins +input pci_clk_i ; +input pci_rst_i ; +output pci_rst_o ; +output pci_rst_oe_o ; + +input pci_inta_i ; +output pci_inta_o ; +output pci_inta_oe_o ; + +// arbitration pins +output pci_req_o ; +output pci_req_oe_o ; + +input pci_gnt_i ; + +// protocol pins +input pci_frame_i ; +output pci_frame_o ; +output pci_frame_oe_o ; +output pci_irdy_oe_o ; +output pci_devsel_oe_o ; +output pci_trdy_oe_o ; +output pci_stop_oe_o ; +output [31:0] pci_ad_oe_o ; +output [3:0] pci_cbe_oe_o ; + +input pci_irdy_i ; +output pci_irdy_o ; + +input pci_idsel_i ; + +input pci_devsel_i ; +output pci_devsel_o ; + +input pci_trdy_i ; +output pci_trdy_o ; + +input pci_stop_i ; +output pci_stop_o ; + +// data transfer pins +input [31:0] pci_ad_i ; +output [31:0] pci_ad_o ; + +input [3:0] pci_cbe_i ; +output [3:0] pci_cbe_o ; + +// parity generation and checking pins +input pci_par_i ; +output pci_par_o ; +output pci_par_oe_o ; + +input pci_perr_i ; +output pci_perr_o ; +output pci_perr_oe_o ; + +// system error pin +output pci_serr_o ; +output pci_serr_oe_o ; + +`ifdef PCI_BIST +/*----------------------------------------------------- +BIST debug chain port signals +-----------------------------------------------------*/ +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +`ifdef PCI_CPCI_HS_IMPLEMENT + // Compact PCI Hot Swap signals +output pci_cpci_hs_enum_o ; // ENUM# output with output enable (open drain) +output pci_cpci_hs_enum_oe_o ; // ENUM# enum output enable +output pci_cpci_hs_led_o ; // LED output with output enable (open drain) +output pci_cpci_hs_led_oe_o ; // LED output enable +input pci_cpci_hs_es_i ; // ejector switch state indicator input + +assign pci_cpci_hs_enum_o = 1'b0 ; +assign pci_cpci_hs_led_o = 1'b0 ; +`endif + +`ifdef PCI_SPOCI +output spoci_scl_o ; +output spoci_scl_oe_o ; +input spoci_sda_i ; +output spoci_sda_o ; +output spoci_sda_oe_o ; + +assign spoci_scl_o = 1'b0 ; +assign spoci_sda_o = 1'b0 ; +`endif + +// declare clock and reset wires +wire pci_clk = pci_clk_i ; +wire wb_clk = wb_clk_i ; +wire reset ; // assigned at pci bridge reset and interrupt logic + +/*========================================================================================================= +First comes definition of all modules' outputs, so they can be assigned to any other module's input later + in the file, when module is instantiated +=========================================================================================================*/ +// PCI BRIDGE RESET AND INTERRUPT LOGIC OUTPUTS +wire pci_reso_reset ; +wire pci_reso_pci_rstn_out ; +wire pci_reso_pci_rstn_en_out ; +wire pci_reso_rst_o ; +wire pci_into_pci_intan_out ; +wire pci_into_pci_intan_en_out ; +wire pci_into_int_o ; +wire pci_into_conf_isr_int_prop_out ; + +// assign pci bridge reset interrupt logic outputs to top outputs where possible +assign reset = pci_reso_reset ; +assign pci_rst_o = pci_reso_pci_rstn_out ; +assign pci_rst_oe_o = pci_reso_pci_rstn_en_out ; +assign wb_rst_o = pci_reso_rst_o ; +assign pci_inta_o = pci_into_pci_intan_out ; +assign pci_inta_oe_o = pci_into_pci_intan_en_out ; +assign wb_int_o = pci_into_int_o ; + +// WISHBONE SLAVE UNIT OUTPUTS +wire [31:0] wbu_sdata_out ; +wire wbu_ack_out ; +wire wbu_rty_out ; +wire wbu_err_out ; +wire wbu_pciif_req_out ; +wire wbu_pciif_frame_out ; +wire wbu_pciif_frame_en_out ; +wire wbu_pciif_irdy_out ; +wire wbu_pciif_irdy_en_out ; +wire [31:0] wbu_pciif_ad_out ; +wire wbu_pciif_ad_en_out ; +wire [3:0] wbu_pciif_cbe_out ; +wire wbu_pciif_cbe_en_out ; +wire [31:0] wbu_err_addr_out ; +wire [3:0] wbu_err_bc_out ; +wire wbu_err_signal_out ; +wire wbu_err_source_out ; +wire wbu_err_rty_exp_out ; +wire wbu_tabort_rec_out ; +wire wbu_mabort_rec_out ; +wire [11:0] wbu_conf_offset_out ; +wire wbu_conf_renable_out ; +wire wbu_conf_wenable_out ; +wire [3:0] wbu_conf_be_out ; +wire [31:0] wbu_conf_data_out ; +wire wbu_del_read_comp_pending_out ; +wire wbu_wbw_fifo_empty_out ; +wire wbu_ad_load_out ; +wire wbu_ad_load_on_transfer_out ; +wire wbu_pciif_frame_load_out ; + +// PCI TARGET UNIT OUTPUTS +wire [31:0] pciu_adr_out ; +wire [31:0] pciu_mdata_out ; +wire pciu_cyc_out ; +wire pciu_stb_out ; +wire pciu_we_out ; +wire [2:0] pciu_cti_out ; +wire [1:0] pciu_bte_out ; +wire [3:0] pciu_sel_out ; +wire pciu_pciif_trdy_out ; +wire pciu_pciif_stop_out ; +wire pciu_pciif_devsel_out ; +wire pciu_pciif_trdy_en_out ; +wire pciu_pciif_stop_en_out ; +wire pciu_pciif_devsel_en_out ; +wire pciu_ad_load_out ; +wire pciu_ad_load_on_transfer_out ; +wire [31:0] pciu_pciif_ad_out ; +wire pciu_pciif_ad_en_out ; +wire pciu_pciif_tabort_set_out ; +wire [31:0] pciu_err_addr_out ; +wire [3:0] pciu_err_bc_out ; +wire [31:0] pciu_err_data_out ; +wire [3:0] pciu_err_be_out ; +wire pciu_err_signal_out ; +wire pciu_err_source_out ; +wire pciu_err_rty_exp_out ; +wire [11:0] pciu_conf_offset_out ; +wire pciu_conf_renable_out ; +wire pciu_conf_wenable_out ; +wire [3:0] pciu_conf_be_out ; +wire [31:0] pciu_conf_data_out ; +wire pciu_pci_drcomp_pending_out ; +wire pciu_pciw_fifo_empty_out ; + +// assign pci target unit's outputs to top outputs where possible +assign wbm_adr_o = pciu_adr_out ; +assign wbm_dat_o = pciu_mdata_out ; +assign wbm_cyc_o = pciu_cyc_out ; +assign wbm_stb_o = pciu_stb_out ; +assign wbm_we_o = pciu_we_out ; +assign wbm_cti_o = pciu_cti_out ; +assign wbm_bte_o = pciu_bte_out ; +assign wbm_sel_o = pciu_sel_out ; + +// CONFIGURATION SPACE OUTPUTS +wire [31:0] conf_w_data_out ; +wire [31:0] conf_r_data_out ; +wire conf_serr_enable_out ; +wire conf_perr_response_out ; +wire conf_pci_master_enable_out ; +wire conf_mem_space_enable_out ; +wire conf_io_space_enable_out ; +wire [7:0] conf_cache_line_size_to_pci_out ; +wire [7:0] conf_cache_line_size_to_wb_out ; +wire conf_cache_lsize_not_zero_to_wb_out ; +wire [7:0] conf_latency_tim_out ; + +wire [pci_ba0_width - 1:0] conf_pci_ba0_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ba1_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ba2_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ba3_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ba4_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ba5_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta0_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta1_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta2_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta3_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta4_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_ta5_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am0_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am1_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am2_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am3_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am4_out ; +wire [pci_ba1_5_width - 1:0] conf_pci_am5_out ; + +wire conf_pci_mem_io0_out ; +wire conf_pci_mem_io1_out ; +wire conf_pci_mem_io2_out ; +wire conf_pci_mem_io3_out ; +wire conf_pci_mem_io4_out ; +wire conf_pci_mem_io5_out ; + +wire [1:0] conf_pci_img_ctrl0_out ; +wire [1:0] conf_pci_img_ctrl1_out ; +wire [1:0] conf_pci_img_ctrl2_out ; +wire [1:0] conf_pci_img_ctrl3_out ; +wire [1:0] conf_pci_img_ctrl4_out ; +wire [1:0] conf_pci_img_ctrl5_out ; + +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba0_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba1_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba2_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba3_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba4_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ba5_out ; + +wire conf_wb_mem_io0_out ; +wire conf_wb_mem_io1_out ; +wire conf_wb_mem_io2_out ; +wire conf_wb_mem_io3_out ; +wire conf_wb_mem_io4_out ; +wire conf_wb_mem_io5_out ; + +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am0_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am1_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am2_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am3_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am4_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_am5_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta0_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta1_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta2_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta3_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta4_out ; +wire [19:(20 - `WB_NUM_OF_DEC_ADDR_LINES)] conf_wb_ta5_out ; +wire [2:0] conf_wb_img_ctrl0_out ; +wire [2:0] conf_wb_img_ctrl1_out ; +wire [2:0] conf_wb_img_ctrl2_out ; +wire [2:0] conf_wb_img_ctrl3_out ; +wire [2:0] conf_wb_img_ctrl4_out ; +wire [2:0] conf_wb_img_ctrl5_out ; +wire [23:0] conf_ccyc_addr_out ; +wire conf_soft_res_out ; +wire conf_int_out ; +wire conf_wb_init_complete_out ; +wire conf_pci_init_complete_out ; + +// PCI IO MUX OUTPUTS +wire pci_mux_frame_out ; +wire pci_mux_irdy_out ; +wire pci_mux_devsel_out ; +wire pci_mux_trdy_out ; +wire pci_mux_stop_out ; +wire [3:0] pci_mux_cbe_out ; +wire [31:0] pci_mux_ad_out ; +wire pci_mux_ad_load_out ; + +wire [31:0] pci_mux_ad_en_out ; +wire pci_mux_ad_en_unregistered_out ; +wire pci_mux_frame_en_out ; +wire pci_mux_irdy_en_out ; +wire pci_mux_devsel_en_out ; +wire pci_mux_trdy_en_out ; +wire pci_mux_stop_en_out ; +wire [3:0] pci_mux_cbe_en_out ; + +wire pci_mux_par_out ; +wire pci_mux_par_en_out ; +wire pci_mux_perr_out ; +wire pci_mux_perr_en_out ; +wire pci_mux_serr_out ; +wire pci_mux_serr_en_out ; + +wire pci_mux_req_out ; +wire pci_mux_req_en_out ; + +// assign outputs to top level outputs + +assign pci_ad_oe_o = pci_mux_ad_en_out ; +assign pci_frame_oe_o = pci_mux_frame_en_out ; +assign pci_irdy_oe_o = pci_mux_irdy_en_out ; +assign pci_cbe_oe_o = pci_mux_cbe_en_out ; + +assign pci_par_o = pci_mux_par_out ; +assign pci_par_oe_o = pci_mux_par_en_out ; +assign pci_perr_o = pci_mux_perr_out ; +assign pci_perr_oe_o = pci_mux_perr_en_out ; +assign pci_serr_o = pci_mux_serr_out ; +assign pci_serr_oe_o = pci_mux_serr_en_out ; + +assign pci_req_o = pci_mux_req_out ; +assign pci_req_oe_o = pci_mux_req_en_out ; + +assign pci_trdy_oe_o = pci_mux_trdy_en_out ; +assign pci_devsel_oe_o = pci_mux_devsel_en_out ; +assign pci_stop_oe_o = pci_mux_stop_en_out ; +assign pci_trdy_o = pci_mux_trdy_out ; +assign pci_devsel_o = pci_mux_devsel_out ; +assign pci_stop_o = pci_mux_stop_out ; + +assign pci_ad_o = pci_mux_ad_out ; +assign pci_frame_o = pci_mux_frame_out ; +assign pci_irdy_o = pci_mux_irdy_out ; +assign pci_cbe_o = pci_mux_cbe_out ; + +// duplicate output register's outputs +wire out_bckp_frame_out ; +wire out_bckp_irdy_out ; +wire out_bckp_devsel_out ; +wire out_bckp_trdy_out ; +wire out_bckp_stop_out ; +wire [3:0] out_bckp_cbe_out ; +wire out_bckp_cbe_en_out ; +wire [31:0] out_bckp_ad_out ; +wire out_bckp_ad_en_out ; +wire out_bckp_irdy_en_out ; +wire out_bckp_frame_en_out ; +wire out_bckp_tar_ad_en_out ; +wire out_bckp_mas_ad_en_out ; +wire out_bckp_trdy_en_out ; + +wire out_bckp_par_out ; +wire out_bckp_par_en_out ; +wire out_bckp_perr_out ; +wire out_bckp_perr_en_out ; +wire out_bckp_serr_out ; +wire out_bckp_serr_en_out ; + +wire int_pci_frame = out_bckp_frame_en_out ? out_bckp_frame_out : pci_frame_i ; +wire int_pci_irdy = out_bckp_irdy_en_out ? out_bckp_irdy_out : pci_irdy_i ; +wire int_pci_devsel = out_bckp_trdy_en_out ? out_bckp_devsel_out : pci_devsel_i ; +wire int_pci_trdy = out_bckp_trdy_en_out ? out_bckp_trdy_out : pci_trdy_i ; +wire int_pci_stop = out_bckp_trdy_en_out ? out_bckp_stop_out : pci_stop_i ; +wire [ 3: 0] int_pci_cbe = out_bckp_cbe_en_out ? out_bckp_cbe_out : pci_cbe_i ; +wire int_pci_par = out_bckp_par_en_out ? out_bckp_par_out : pci_par_i ; +wire int_pci_perr = out_bckp_perr_en_out ? out_bckp_perr_out : pci_perr_i ; +// PARITY CHECKER OUTPUTS +wire parchk_pci_par_out ; +wire parchk_pci_par_en_out ; +wire parchk_pci_perr_out ; +wire parchk_pci_perr_en_out ; +wire parchk_pci_serr_out ; +wire parchk_pci_serr_en_out ; +wire parchk_par_err_detect_out ; +wire parchk_perr_mas_detect_out ; +wire parchk_sig_serr_out ; + +// input register outputs +wire in_reg_gnt_out ; +wire in_reg_frame_out ; +wire in_reg_irdy_out ; +wire in_reg_trdy_out ; +wire in_reg_stop_out ; +wire in_reg_devsel_out ; +wire in_reg_idsel_out ; +wire [31:0] in_reg_ad_out ; +wire [3:0] in_reg_cbe_out ; + +/*========================================================================================================= +Now comes definition of all modules' and their appropriate inputs +=========================================================================================================*/ +// PCI BRIDGE RESET AND INTERRUPT LOGIC INPUTS +wire pci_resi_rst_i = wb_rst_i ; +wire pci_resi_pci_rstn_in = pci_rst_i ; +wire pci_resi_conf_soft_res_in = conf_soft_res_out ; +wire pci_inti_pci_intan_in = pci_inta_i ; +wire pci_inti_conf_int_in = conf_int_out ; +wire pci_inti_int_i = wb_int_i ; +wire pci_into_init_complete_in = conf_pci_init_complete_out ; + +pci_rst_int pci_resets_and_interrupts +( + .clk_in (pci_clk), + .rst_i (pci_resi_rst_i), + .pci_rstn_in (pci_resi_pci_rstn_in), + .conf_soft_res_in (pci_resi_conf_soft_res_in), + .reset (pci_reso_reset), + .pci_rstn_out (pci_reso_pci_rstn_out), + .pci_rstn_en_out (pci_reso_pci_rstn_en_out), + .rst_o (pci_reso_rst_o), + .pci_intan_in (pci_inti_pci_intan_in), + .conf_int_in (pci_inti_conf_int_in), + .int_i (pci_inti_int_i), + .pci_intan_out (pci_into_pci_intan_out), + .pci_intan_en_out (pci_into_pci_intan_en_out), + .int_o (pci_into_int_o), + .conf_isr_int_prop_out (pci_into_conf_isr_int_prop_out), + .init_complete_in (pci_into_init_complete_in) +); + + +`ifdef PCI_WB_REV_B3 + +wire wbs_wbb3_2_wbb2_cyc_o ; +wire wbs_wbb3_2_wbb2_stb_o ; +wire [31:0] wbs_wbb3_2_wbb2_adr_o ; +wire [31:0] wbs_wbb3_2_wbb2_dat_i_o ; +wire [31:0] wbs_wbb3_2_wbb2_dat_o_o ; +wire wbs_wbb3_2_wbb2_we_o ; +wire [ 3:0] wbs_wbb3_2_wbb2_sel_o ; +wire wbs_wbb3_2_wbb2_ack_o ; +wire wbs_wbb3_2_wbb2_err_o ; +wire wbs_wbb3_2_wbb2_rty_o ; +wire wbs_wbb3_2_wbb2_cab_o ; + +// assign wishbone slave unit's outputs to top outputs where possible +assign wbs_dat_o = wbs_wbb3_2_wbb2_dat_o_o ; +assign wbs_ack_o = wbs_wbb3_2_wbb2_ack_o ; +assign wbs_rty_o = wbs_wbb3_2_wbb2_rty_o ; +assign wbs_err_o = wbs_wbb3_2_wbb2_err_o ; + +wire wbs_wbb3_2_wbb2_cyc_i = wbs_cyc_i ; +wire wbs_wbb3_2_wbb2_stb_i = wbs_stb_i ; +wire wbs_wbb3_2_wbb2_we_i = wbs_we_i ; +wire wbs_wbb3_2_wbb2_ack_i = wbu_ack_out ; +wire wbs_wbb3_2_wbb2_err_i = wbu_err_out ; +wire wbs_wbb3_2_wbb2_rty_i = wbu_rty_out ; +wire [31:0] wbs_wbb3_2_wbb2_adr_i = wbs_adr_i ; +wire [ 3:0] wbs_wbb3_2_wbb2_sel_i = wbs_sel_i ; +wire [31:0] wbs_wbb3_2_wbb2_dat_i_i = wbs_dat_i ; +wire [31:0] wbs_wbb3_2_wbb2_dat_o_i = wbu_sdata_out ; +wire [ 2:0] wbs_wbb3_2_wbb2_cti_i = wbs_cti_i ; +wire [ 1:0] wbs_wbb3_2_wbb2_bte_i = wbs_bte_i ; + +pci_wbs_wbb3_2_wbb2 i_pci_wbs_wbb3_2_wbb2 +( + .wb_clk_i ( wb_clk_i ) , + .wb_rst_i ( reset ) , + + .wbs_cyc_i ( wbs_wbb3_2_wbb2_cyc_i ) , + .wbs_cyc_o ( wbs_wbb3_2_wbb2_cyc_o ) , + .wbs_stb_i ( wbs_wbb3_2_wbb2_stb_i ) , + .wbs_stb_o ( wbs_wbb3_2_wbb2_stb_o ) , + .wbs_adr_i ( wbs_wbb3_2_wbb2_adr_i ) , + .wbs_adr_o ( wbs_wbb3_2_wbb2_adr_o ) , + .wbs_dat_i_i ( wbs_wbb3_2_wbb2_dat_i_i ) , + .wbs_dat_i_o ( wbs_wbb3_2_wbb2_dat_i_o ) , + .wbs_dat_o_i ( wbs_wbb3_2_wbb2_dat_o_i ) , + .wbs_dat_o_o ( wbs_wbb3_2_wbb2_dat_o_o ) , + .wbs_we_i ( wbs_wbb3_2_wbb2_we_i ) , + .wbs_we_o ( wbs_wbb3_2_wbb2_we_o ) , + .wbs_sel_i ( wbs_wbb3_2_wbb2_sel_i ) , + .wbs_sel_o ( wbs_wbb3_2_wbb2_sel_o ) , + .wbs_ack_i ( wbs_wbb3_2_wbb2_ack_i ) , + .wbs_ack_o ( wbs_wbb3_2_wbb2_ack_o ) , + .wbs_err_i ( wbs_wbb3_2_wbb2_err_i ) , + .wbs_err_o ( wbs_wbb3_2_wbb2_err_o ) , + .wbs_rty_i ( wbs_wbb3_2_wbb2_rty_i ) , + .wbs_rty_o ( wbs_wbb3_2_wbb2_rty_o ) , + .wbs_cti_i ( wbs_wbb3_2_wbb2_cti_i ) , + .wbs_bte_i ( wbs_wbb3_2_wbb2_bte_i ) , + .wbs_cab_o ( wbs_wbb3_2_wbb2_cab_o ) , + .wb_init_complete_i ( conf_wb_init_complete_out ) +) ; + +// WISHBONE SLAVE UNIT INPUTS +wire [31:0] wbu_addr_in = wbs_wbb3_2_wbb2_adr_o ; +wire [31:0] wbu_sdata_in = wbs_wbb3_2_wbb2_dat_i_o ; +wire wbu_cyc_in = wbs_wbb3_2_wbb2_cyc_o ; +wire wbu_stb_in = wbs_wbb3_2_wbb2_stb_o ; +wire wbu_we_in = wbs_wbb3_2_wbb2_we_o ; +wire [3:0] wbu_sel_in = wbs_wbb3_2_wbb2_sel_o ; +wire wbu_cab_in = wbs_wbb3_2_wbb2_cab_o ; + +`else + +// WISHBONE SLAVE UNIT INPUTS +wire [31:0] wbu_addr_in = wbs_adr_i ; +wire [31:0] wbu_sdata_in = wbs_dat_i ; +wire wbu_cyc_in = wbs_cyc_i ; +wire wbu_stb_in = wbs_stb_i ; +wire wbu_we_in = wbs_we_i ; +wire [3:0] wbu_sel_in = wbs_sel_i ; +wire wbu_cab_in = wbs_cab_i ; + +// assign wishbone slave unit's outputs to top outputs where possible +assign wbs_dat_o = wbu_sdata_out ; +assign wbs_ack_o = wbu_ack_out ; +assign wbs_rty_o = wbu_rty_out ; +assign wbs_err_o = wbu_err_out ; + +`endif + +wire [5:0] wbu_map_in = { + conf_wb_mem_io5_out, + conf_wb_mem_io4_out, + conf_wb_mem_io3_out, + conf_wb_mem_io2_out, + conf_wb_mem_io1_out, + conf_wb_mem_io0_out + } ; + +wire [5:0] wbu_pref_en_in = { + conf_wb_img_ctrl5_out[1], + conf_wb_img_ctrl4_out[1], + conf_wb_img_ctrl3_out[1], + conf_wb_img_ctrl2_out[1], + conf_wb_img_ctrl1_out[1], + conf_wb_img_ctrl0_out[1] + }; +wire [5:0] wbu_mrl_en_in = { + conf_wb_img_ctrl5_out[0], + conf_wb_img_ctrl4_out[0], + conf_wb_img_ctrl3_out[0], + conf_wb_img_ctrl2_out[0], + conf_wb_img_ctrl1_out[0], + conf_wb_img_ctrl0_out[0] + }; + +wire [5:0] wbu_at_en_in = { + conf_wb_img_ctrl5_out[2], + conf_wb_img_ctrl4_out[2], + conf_wb_img_ctrl3_out[2], + conf_wb_img_ctrl2_out[2], + conf_wb_img_ctrl1_out[2], + conf_wb_img_ctrl0_out[2] + } ; + +wire wbu_pci_drcomp_pending_in = pciu_pci_drcomp_pending_out ; +wire wbu_pciw_empty_in = pciu_pciw_fifo_empty_out ; + +`ifdef HOST + wire [31:0] wbu_conf_data_in = conf_w_data_out ; +`else +`ifdef GUEST + wire [31:0] wbu_conf_data_in = conf_r_data_out ; +`endif +`endif + +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar0_in = conf_wb_ba0_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar1_in = conf_wb_ba1_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar2_in = conf_wb_ba2_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar3_in = conf_wb_ba3_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar4_in = conf_wb_ba4_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar5_in = conf_wb_ba5_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am0_in = conf_wb_am0_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am1_in = conf_wb_am1_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am2_in = conf_wb_am2_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am3_in = conf_wb_am3_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am4_in = conf_wb_am4_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am5_in = conf_wb_am5_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta0_in = conf_wb_ta0_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta1_in = conf_wb_ta1_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta2_in = conf_wb_ta2_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta3_in = conf_wb_ta3_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta4_in = conf_wb_ta4_out ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta5_in = conf_wb_ta5_out ; + +wire [23:0] wbu_ccyc_addr_in = conf_ccyc_addr_out ; +wire wbu_master_enable_in = conf_pci_master_enable_out ; +wire wbu_cache_line_size_not_zero = conf_cache_lsize_not_zero_to_wb_out ; +wire [7:0] wbu_cache_line_size_in = conf_cache_line_size_to_pci_out ; + +wire wbu_pciif_gnt_in = pci_gnt_i ; +wire wbu_pciif_frame_in = in_reg_frame_out ; +wire wbu_pciif_irdy_in = in_reg_irdy_out ; +wire wbu_pciif_trdy_in = int_pci_trdy ; +wire wbu_pciif_stop_in = int_pci_stop ; +wire wbu_pciif_devsel_in = int_pci_devsel ; +wire [31:0] wbu_pciif_ad_reg_in = in_reg_ad_out ; +wire wbu_pciif_trdy_reg_in = in_reg_trdy_out ; +wire wbu_pciif_stop_reg_in = in_reg_stop_out ; +wire wbu_pciif_devsel_reg_in = in_reg_devsel_out ; + + +wire [7:0] wbu_latency_tim_val_in = conf_latency_tim_out ; + +wire wbu_pciif_frame_en_in = out_bckp_frame_en_out ; +wire wbu_pciif_frame_out_in = out_bckp_frame_out ; +wire wbu_wb_init_complete_in = conf_wb_init_complete_out ; + +pci_wb_slave_unit wishbone_slave_unit +( + .reset_in (reset), + .wb_clock_in (wb_clk), + .pci_clock_in (pci_clk), + .ADDR_I (wbu_addr_in), + .SDATA_I (wbu_sdata_in), + .SDATA_O (wbu_sdata_out), + .CYC_I (wbu_cyc_in), + .STB_I (wbu_stb_in), + .WE_I (wbu_we_in), + .SEL_I (wbu_sel_in), + .ACK_O (wbu_ack_out), + .RTY_O (wbu_rty_out), + .ERR_O (wbu_err_out), + .CAB_I (wbu_cab_in), + .wbu_map_in (wbu_map_in), + .wbu_pref_en_in (wbu_pref_en_in), + .wbu_mrl_en_in (wbu_mrl_en_in), + .wbu_pci_drcomp_pending_in (wbu_pci_drcomp_pending_in), + .wbu_conf_data_in (wbu_conf_data_in), + .wbu_pciw_empty_in (wbu_pciw_empty_in), + .wbu_bar0_in (wbu_bar0_in), + .wbu_bar1_in (wbu_bar1_in), + .wbu_bar2_in (wbu_bar2_in), + .wbu_bar3_in (wbu_bar3_in), + .wbu_bar4_in (wbu_bar4_in), + .wbu_bar5_in (wbu_bar5_in), + .wbu_am0_in (wbu_am0_in), + .wbu_am1_in (wbu_am1_in), + .wbu_am2_in (wbu_am2_in), + .wbu_am3_in (wbu_am3_in), + .wbu_am4_in (wbu_am4_in), + .wbu_am5_in (wbu_am5_in), + .wbu_ta0_in (wbu_ta0_in), + .wbu_ta1_in (wbu_ta1_in), + .wbu_ta2_in (wbu_ta2_in), + .wbu_ta3_in (wbu_ta3_in), + .wbu_ta4_in (wbu_ta4_in), + .wbu_ta5_in (wbu_ta5_in), + .wbu_at_en_in (wbu_at_en_in), + .wbu_ccyc_addr_in (wbu_ccyc_addr_in), + .wbu_master_enable_in (wbu_master_enable_in), + .wb_init_complete_in (wbu_wb_init_complete_in), + .wbu_cache_line_size_not_zero (wbu_cache_line_size_not_zero), + .wbu_cache_line_size_in (wbu_cache_line_size_in), + .wbu_pciif_gnt_in (wbu_pciif_gnt_in), + .wbu_pciif_frame_in (wbu_pciif_frame_in), + .wbu_pciif_frame_en_in (wbu_pciif_frame_en_in), + .wbu_pciif_frame_out_in (wbu_pciif_frame_out_in), + .wbu_pciif_irdy_in (wbu_pciif_irdy_in), + .wbu_pciif_trdy_in (wbu_pciif_trdy_in), + .wbu_pciif_stop_in (wbu_pciif_stop_in), + .wbu_pciif_devsel_in (wbu_pciif_devsel_in), + .wbu_pciif_ad_reg_in (wbu_pciif_ad_reg_in), + .wbu_pciif_req_out (wbu_pciif_req_out), + .wbu_pciif_frame_out (wbu_pciif_frame_out), + .wbu_pciif_frame_en_out (wbu_pciif_frame_en_out), + .wbu_pciif_frame_load_out (wbu_pciif_frame_load_out), + .wbu_pciif_irdy_out (wbu_pciif_irdy_out), + .wbu_pciif_irdy_en_out (wbu_pciif_irdy_en_out), + .wbu_pciif_ad_out (wbu_pciif_ad_out), + .wbu_pciif_ad_en_out (wbu_pciif_ad_en_out), + .wbu_pciif_cbe_out (wbu_pciif_cbe_out), + .wbu_pciif_cbe_en_out (wbu_pciif_cbe_en_out), + .wbu_err_addr_out (wbu_err_addr_out), + .wbu_err_bc_out (wbu_err_bc_out), + .wbu_err_signal_out (wbu_err_signal_out), + .wbu_err_source_out (wbu_err_source_out), + .wbu_err_rty_exp_out (wbu_err_rty_exp_out), + .wbu_tabort_rec_out (wbu_tabort_rec_out), + .wbu_mabort_rec_out (wbu_mabort_rec_out), + .wbu_conf_offset_out (wbu_conf_offset_out), + .wbu_conf_renable_out (wbu_conf_renable_out), + .wbu_conf_wenable_out (wbu_conf_wenable_out), + .wbu_conf_be_out (wbu_conf_be_out), + .wbu_conf_data_out (wbu_conf_data_out), + .wbu_del_read_comp_pending_out (wbu_del_read_comp_pending_out), + .wbu_wbw_fifo_empty_out (wbu_wbw_fifo_empty_out), + .wbu_latency_tim_val_in (wbu_latency_tim_val_in), + .wbu_ad_load_out (wbu_ad_load_out), + .wbu_ad_load_on_transfer_out (wbu_ad_load_on_transfer_out), + .wbu_pciif_trdy_reg_in (wbu_pciif_trdy_reg_in), + .wbu_pciif_stop_reg_in (wbu_pciif_stop_reg_in), + .wbu_pciif_devsel_reg_in (wbu_pciif_devsel_reg_in) + +`ifdef PCI_BIST + , + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o_internal), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +); + +// PCI TARGET UNIT INPUTS +wire [31:0] pciu_mdata_in = wbm_dat_i ; +wire pciu_ack_in = wbm_ack_i ; +wire pciu_rty_in = wbm_rty_i ; +wire pciu_err_in = wbm_err_i ; + +wire [5:0] pciu_map_in = { + conf_pci_mem_io5_out, + conf_pci_mem_io4_out, + conf_pci_mem_io3_out, + conf_pci_mem_io2_out, + conf_pci_mem_io1_out, + conf_pci_mem_io0_out + } ; + +wire [5:0] pciu_pref_en_in = { + conf_pci_img_ctrl5_out[0], + conf_pci_img_ctrl4_out[0], + conf_pci_img_ctrl3_out[0], + conf_pci_img_ctrl2_out[0], + conf_pci_img_ctrl1_out[0], + conf_pci_img_ctrl0_out[0] + }; + +wire [5:0] pciu_at_en_in = { + conf_pci_img_ctrl5_out[1], + conf_pci_img_ctrl4_out[1], + conf_pci_img_ctrl3_out[1], + conf_pci_img_ctrl2_out[1], + conf_pci_img_ctrl1_out[1], + conf_pci_img_ctrl0_out[1] + } ; + +wire pciu_mem_enable_in = conf_mem_space_enable_out ; +wire pciu_io_enable_in = conf_io_space_enable_out ; + +wire pciu_wbw_fifo_empty_in = wbu_wbw_fifo_empty_out ; +wire pciu_wbu_del_read_comp_pending_in = wbu_del_read_comp_pending_out ; +wire pciu_wbu_frame_en_in = out_bckp_frame_en_out ; + +`ifdef HOST + wire [31:0] pciu_conf_data_in = conf_r_data_out ; +`else +`ifdef GUEST + wire [31:0] pciu_conf_data_in = conf_w_data_out ; +`endif +`endif + +wire [pci_ba0_width - 1:0] pciu_bar0_in = conf_pci_ba0_out ; +wire [pci_ba1_5_width - 1:0] pciu_bar1_in = conf_pci_ba1_out ; +wire [pci_ba1_5_width - 1:0] pciu_bar2_in = conf_pci_ba2_out ; +wire [pci_ba1_5_width - 1:0] pciu_bar3_in = conf_pci_ba3_out ; +wire [pci_ba1_5_width - 1:0] pciu_bar4_in = conf_pci_ba4_out ; +wire [pci_ba1_5_width - 1:0] pciu_bar5_in = conf_pci_ba5_out ; +wire [pci_ba1_5_width - 1:0] pciu_am0_in = conf_pci_am0_out ; +wire [pci_ba1_5_width - 1:0] pciu_am1_in = conf_pci_am1_out ; +wire [pci_ba1_5_width - 1:0] pciu_am2_in = conf_pci_am2_out ; +wire [pci_ba1_5_width - 1:0] pciu_am3_in = conf_pci_am3_out ; +wire [pci_ba1_5_width - 1:0] pciu_am4_in = conf_pci_am4_out ; +wire [pci_ba1_5_width - 1:0] pciu_am5_in = conf_pci_am5_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta0_in = conf_pci_ta0_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta1_in = conf_pci_ta1_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta2_in = conf_pci_ta2_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta3_in = conf_pci_ta3_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta4_in = conf_pci_ta4_out ; +wire [pci_ba1_5_width - 1:0] pciu_ta5_in = conf_pci_ta5_out ; + +wire [7:0] pciu_cache_line_size_in = conf_cache_line_size_to_wb_out ; +wire pciu_cache_lsize_not_zero_in = conf_cache_lsize_not_zero_to_wb_out ; + +wire pciu_pciif_frame_in = int_pci_frame ; +wire pciu_pciif_irdy_in = int_pci_irdy ; +wire pciu_pciif_idsel_in = pci_idsel_i ; +wire pciu_pciif_frame_reg_in = in_reg_frame_out ; +wire pciu_pciif_irdy_reg_in = in_reg_irdy_out ; +wire pciu_pciif_idsel_reg_in = in_reg_idsel_out ; +wire [31:0] pciu_pciif_ad_reg_in = in_reg_ad_out ; +wire [3:0] pciu_pciif_cbe_reg_in = in_reg_cbe_out ; +wire [3:0] pciu_pciif_cbe_in = int_pci_cbe ; + +wire pciu_pciif_bckp_trdy_en_in = out_bckp_trdy_en_out ; +wire pciu_pciif_bckp_devsel_in = out_bckp_devsel_out ; +wire pciu_pciif_bckp_trdy_in = out_bckp_trdy_out ; +wire pciu_pciif_bckp_stop_in = out_bckp_stop_out ; +wire pciu_pciif_trdy_reg_in = in_reg_trdy_out ; +wire pciu_pciif_stop_reg_in = in_reg_stop_out ; + +pci_target_unit pci_target_unit +( + .reset_in (reset), + .wb_clock_in (wb_clk), + .pci_clock_in (pci_clk), + .pciu_wbm_adr_o (pciu_adr_out), + .pciu_wbm_dat_o (pciu_mdata_out), + .pciu_wbm_dat_i (pciu_mdata_in), + .pciu_wbm_cyc_o (pciu_cyc_out), + .pciu_wbm_stb_o (pciu_stb_out), + .pciu_wbm_we_o (pciu_we_out), + .pciu_wbm_cti_o (pciu_cti_out), + .pciu_wbm_bte_o (pciu_bte_out), + .pciu_wbm_sel_o (pciu_sel_out), + .pciu_wbm_ack_i (pciu_ack_in), + .pciu_wbm_rty_i (pciu_rty_in), + .pciu_wbm_err_i (pciu_err_in), + .pciu_mem_enable_in (pciu_mem_enable_in), + .pciu_io_enable_in (pciu_io_enable_in), + .pciu_map_in (pciu_map_in), + .pciu_pref_en_in (pciu_pref_en_in), + .pciu_conf_data_in (pciu_conf_data_in), + .pciu_wbw_fifo_empty_in (pciu_wbw_fifo_empty_in), + .pciu_wbu_del_read_comp_pending_in (pciu_wbu_del_read_comp_pending_in), + .pciu_wbu_frame_en_in (pciu_wbu_frame_en_in), + .pciu_bar0_in (pciu_bar0_in), + .pciu_bar1_in (pciu_bar1_in), + .pciu_bar2_in (pciu_bar2_in), + .pciu_bar3_in (pciu_bar3_in), + .pciu_bar4_in (pciu_bar4_in), + .pciu_bar5_in (pciu_bar5_in), + .pciu_am0_in (pciu_am0_in), + .pciu_am1_in (pciu_am1_in), + .pciu_am2_in (pciu_am2_in), + .pciu_am3_in (pciu_am3_in), + .pciu_am4_in (pciu_am4_in), + .pciu_am5_in (pciu_am5_in), + .pciu_ta0_in (pciu_ta0_in), + .pciu_ta1_in (pciu_ta1_in), + .pciu_ta2_in (pciu_ta2_in), + .pciu_ta3_in (pciu_ta3_in), + .pciu_ta4_in (pciu_ta4_in), + .pciu_ta5_in (pciu_ta5_in), + .pciu_at_en_in (pciu_at_en_in), + .pciu_cache_line_size_in (pciu_cache_line_size_in), + .pciu_cache_lsize_not_zero_in (pciu_cache_lsize_not_zero_in), + .pciu_pciif_frame_in (pciu_pciif_frame_in), + .pciu_pciif_irdy_in (pciu_pciif_irdy_in), + .pciu_pciif_idsel_in (pciu_pciif_idsel_in), + .pciu_pciif_frame_reg_in (pciu_pciif_frame_reg_in), + .pciu_pciif_irdy_reg_in (pciu_pciif_irdy_reg_in), + .pciu_pciif_idsel_reg_in (pciu_pciif_idsel_reg_in), + .pciu_pciif_ad_reg_in (pciu_pciif_ad_reg_in), + .pciu_pciif_cbe_reg_in (pciu_pciif_cbe_reg_in), + .pciu_pciif_cbe_in (pciu_pciif_cbe_in), + .pciu_pciif_bckp_trdy_en_in (pciu_pciif_bckp_trdy_en_in), + .pciu_pciif_bckp_devsel_in (pciu_pciif_bckp_devsel_in), + .pciu_pciif_bckp_trdy_in (pciu_pciif_bckp_trdy_in), + .pciu_pciif_bckp_stop_in (pciu_pciif_bckp_stop_in), + .pciu_pciif_trdy_reg_in (pciu_pciif_trdy_reg_in), + .pciu_pciif_stop_reg_in (pciu_pciif_stop_reg_in), + .pciu_pciif_trdy_out (pciu_pciif_trdy_out), + .pciu_pciif_stop_out (pciu_pciif_stop_out), + .pciu_pciif_devsel_out (pciu_pciif_devsel_out), + .pciu_pciif_trdy_en_out (pciu_pciif_trdy_en_out), + .pciu_pciif_stop_en_out (pciu_pciif_stop_en_out), + .pciu_pciif_devsel_en_out (pciu_pciif_devsel_en_out), + .pciu_ad_load_out (pciu_ad_load_out), + .pciu_ad_load_on_transfer_out (pciu_ad_load_on_transfer_out), + .pciu_pciif_ad_out (pciu_pciif_ad_out), + .pciu_pciif_ad_en_out (pciu_pciif_ad_en_out), + .pciu_pciif_tabort_set_out (pciu_pciif_tabort_set_out), + .pciu_err_addr_out (pciu_err_addr_out), + .pciu_err_bc_out (pciu_err_bc_out), + .pciu_err_data_out (pciu_err_data_out), + .pciu_err_be_out (pciu_err_be_out), + .pciu_err_signal_out (pciu_err_signal_out), + .pciu_err_source_out (pciu_err_source_out), + .pciu_err_rty_exp_out (pciu_err_rty_exp_out), + .pciu_conf_offset_out (pciu_conf_offset_out), + .pciu_conf_renable_out (pciu_conf_renable_out), + .pciu_conf_wenable_out (pciu_conf_wenable_out), + .pciu_conf_be_out (pciu_conf_be_out), + .pciu_conf_data_out (pciu_conf_data_out), + .pciu_pci_drcomp_pending_out (pciu_pci_drcomp_pending_out), + .pciu_pciw_fifo_empty_out (pciu_pciw_fifo_empty_out) + +`ifdef PCI_BIST + , + .mbist_si_i (mbist_so_o_internal), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +); + + +// CONFIGURATION SPACE INPUTS +`ifdef HOST + + wire [11:0] conf_w_addr_in = wbu_conf_offset_out ; + wire [31:0] conf_w_data_in = wbu_conf_data_out ; + wire conf_w_we_in = wbu_conf_wenable_out ; + wire conf_w_re_in = wbu_conf_renable_out ; + wire [3:0] conf_w_be_in = wbu_conf_be_out ; + wire conf_w_clock = wb_clk ; + wire [11:0] conf_r_addr_in = pciu_conf_offset_out ; + wire conf_r_re_in = pciu_conf_renable_out ; + +`else +`ifdef GUEST + + wire [11:0] conf_r_addr_in = wbu_conf_offset_out ; + wire conf_r_re_in = wbu_conf_renable_out ; + wire conf_w_clock = pci_clk ; + wire [11:0] conf_w_addr_in = pciu_conf_offset_out ; + wire [31:0] conf_w_data_in = pciu_conf_data_out ; + wire conf_w_we_in = pciu_conf_wenable_out ; + wire conf_w_re_in = pciu_conf_renable_out ; + wire [3:0] conf_w_be_in = pciu_conf_be_out ; + +`endif +`endif + + +wire conf_perr_in = parchk_par_err_detect_out ; +wire conf_serr_in = parchk_sig_serr_out ; +wire conf_master_abort_recv_in = wbu_mabort_rec_out ; +wire conf_target_abort_recv_in = wbu_tabort_rec_out ; +wire conf_target_abort_set_in = pciu_pciif_tabort_set_out ; + +wire conf_master_data_par_err_in = parchk_perr_mas_detect_out ; + +wire [3:0] conf_pci_err_be_in = pciu_err_be_out ; +wire [3:0] conf_pci_err_bc_in = pciu_err_bc_out; +wire conf_pci_err_es_in = pciu_err_source_out ; +wire conf_pci_err_rty_exp_in = pciu_err_rty_exp_out ; +wire conf_pci_err_sig_in = pciu_err_signal_out ; +wire [31:0] conf_pci_err_addr_in = pciu_err_addr_out ; +wire [31:0] conf_pci_err_data_in = pciu_err_data_out ; + +wire [3:0] conf_wb_err_be_in = out_bckp_cbe_out ; +wire [3:0] conf_wb_err_bc_in = wbu_err_bc_out ; +wire conf_wb_err_rty_exp_in = wbu_err_rty_exp_out ; +wire conf_wb_err_es_in = wbu_err_source_out ; +wire conf_wb_err_sig_in = wbu_err_signal_out ; +wire [31:0] conf_wb_err_addr_in = wbu_err_addr_out ; +wire [31:0] conf_wb_err_data_in = out_bckp_ad_out ; + +wire conf_isr_int_prop_in = pci_into_conf_isr_int_prop_out ; +wire conf_par_err_int_in = parchk_perr_mas_detect_out ; +wire conf_sys_err_int_in = parchk_sig_serr_out ; + +pci_conf_space configuration( + .reset (reset), + .pci_clk (pci_clk), + .wb_clk (wb_clk), + .w_conf_address_in (conf_w_addr_in), + .w_conf_data_in (conf_w_data_in), + .w_conf_data_out (conf_w_data_out), + .r_conf_address_in (conf_r_addr_in), + .r_conf_data_out (conf_r_data_out), + .w_we_i (conf_w_we_in), + .w_re (conf_w_re_in), + .r_re (conf_r_re_in), + .w_byte_en_in (conf_w_be_in), + .w_clock (conf_w_clock), + .serr_enable (conf_serr_enable_out), + .perr_response (conf_perr_response_out), + .pci_master_enable (conf_pci_master_enable_out), + .memory_space_enable (conf_mem_space_enable_out), + .io_space_enable (conf_io_space_enable_out), + .perr_in (conf_perr_in), + .serr_in (conf_serr_in), + .master_abort_recv (conf_master_abort_recv_in), + .target_abort_recv (conf_target_abort_recv_in), + .target_abort_set (conf_target_abort_set_in), + .master_data_par_err (conf_master_data_par_err_in), + .cache_line_size_to_pci (conf_cache_line_size_to_pci_out), + .cache_line_size_to_wb (conf_cache_line_size_to_wb_out), + .cache_lsize_not_zero_to_wb (conf_cache_lsize_not_zero_to_wb_out), + .latency_tim (conf_latency_tim_out), + .pci_base_addr0 (conf_pci_ba0_out), + .pci_base_addr1 (conf_pci_ba1_out), + .pci_base_addr2 (conf_pci_ba2_out), + .pci_base_addr3 (conf_pci_ba3_out), + .pci_base_addr4 (conf_pci_ba4_out), + .pci_base_addr5 (conf_pci_ba5_out), + .pci_memory_io0 (conf_pci_mem_io0_out), + .pci_memory_io1 (conf_pci_mem_io1_out), + .pci_memory_io2 (conf_pci_mem_io2_out), + .pci_memory_io3 (conf_pci_mem_io3_out), + .pci_memory_io4 (conf_pci_mem_io4_out), + .pci_memory_io5 (conf_pci_mem_io5_out), + .pci_addr_mask0 (conf_pci_am0_out), + .pci_addr_mask1 (conf_pci_am1_out), + .pci_addr_mask2 (conf_pci_am2_out), + .pci_addr_mask3 (conf_pci_am3_out), + .pci_addr_mask4 (conf_pci_am4_out), + .pci_addr_mask5 (conf_pci_am5_out), + .pci_tran_addr0 (conf_pci_ta0_out), + .pci_tran_addr1 (conf_pci_ta1_out), + .pci_tran_addr2 (conf_pci_ta2_out), + .pci_tran_addr3 (conf_pci_ta3_out), + .pci_tran_addr4 (conf_pci_ta4_out), + .pci_tran_addr5 (conf_pci_ta5_out), + .pci_img_ctrl0 (conf_pci_img_ctrl0_out), + .pci_img_ctrl1 (conf_pci_img_ctrl1_out), + .pci_img_ctrl2 (conf_pci_img_ctrl2_out), + .pci_img_ctrl3 (conf_pci_img_ctrl3_out), + .pci_img_ctrl4 (conf_pci_img_ctrl4_out), + .pci_img_ctrl5 (conf_pci_img_ctrl5_out), + .pci_error_be (conf_pci_err_be_in), + .pci_error_bc (conf_pci_err_bc_in), + .pci_error_rty_exp (conf_pci_err_rty_exp_in), + .pci_error_es (conf_pci_err_es_in), + .pci_error_sig (conf_pci_err_sig_in), + .pci_error_addr (conf_pci_err_addr_in), + .pci_error_data (conf_pci_err_data_in), + .wb_base_addr0 (conf_wb_ba0_out), + .wb_base_addr1 (conf_wb_ba1_out), + .wb_base_addr2 (conf_wb_ba2_out), + .wb_base_addr3 (conf_wb_ba3_out), + .wb_base_addr4 (conf_wb_ba4_out), + .wb_base_addr5 (conf_wb_ba5_out), + .wb_memory_io0 (conf_wb_mem_io0_out), + .wb_memory_io1 (conf_wb_mem_io1_out), + .wb_memory_io2 (conf_wb_mem_io2_out), + .wb_memory_io3 (conf_wb_mem_io3_out), + .wb_memory_io4 (conf_wb_mem_io4_out), + .wb_memory_io5 (conf_wb_mem_io5_out), + .wb_addr_mask0 (conf_wb_am0_out), + .wb_addr_mask1 (conf_wb_am1_out), + .wb_addr_mask2 (conf_wb_am2_out), + .wb_addr_mask3 (conf_wb_am3_out), + .wb_addr_mask4 (conf_wb_am4_out), + .wb_addr_mask5 (conf_wb_am5_out), + .wb_tran_addr0 (conf_wb_ta0_out), + .wb_tran_addr1 (conf_wb_ta1_out), + .wb_tran_addr2 (conf_wb_ta2_out), + .wb_tran_addr3 (conf_wb_ta3_out), + .wb_tran_addr4 (conf_wb_ta4_out), + .wb_tran_addr5 (conf_wb_ta5_out), + .wb_img_ctrl0 (conf_wb_img_ctrl0_out), + .wb_img_ctrl1 (conf_wb_img_ctrl1_out), + .wb_img_ctrl2 (conf_wb_img_ctrl2_out), + .wb_img_ctrl3 (conf_wb_img_ctrl3_out), + .wb_img_ctrl4 (conf_wb_img_ctrl4_out), + .wb_img_ctrl5 (conf_wb_img_ctrl5_out), + .wb_error_be (conf_wb_err_be_in), + .wb_error_bc (conf_wb_err_bc_in), + .wb_error_rty_exp (conf_wb_err_rty_exp_in), + .wb_error_es (conf_wb_err_es_in), + .wb_error_sig (conf_wb_err_sig_in), + .wb_error_addr (conf_wb_err_addr_in), + .wb_error_data (conf_wb_err_data_in), + .config_addr (conf_ccyc_addr_out), + .icr_soft_res (conf_soft_res_out), + .int_out (conf_int_out), + .isr_int_prop (conf_isr_int_prop_in), + .isr_par_err_int (conf_par_err_int_in), + .isr_sys_err_int (conf_sys_err_int_in), + + .pci_init_complete_out (conf_pci_init_complete_out), + .wb_init_complete_out (conf_wb_init_complete_out) + + `ifdef PCI_CPCI_HS_IMPLEMENT + , + .pci_cpci_hs_enum_oe_o (pci_cpci_hs_enum_oe_o) , + .pci_cpci_hs_led_oe_o (pci_cpci_hs_led_oe_o ) , + .pci_cpci_hs_es_i (pci_cpci_hs_es_i) + `endif + + `ifdef PCI_SPOCI + , + // Serial power on configuration interface + .spoci_scl_oe_o (spoci_scl_oe_o ) , + .spoci_sda_i (spoci_sda_i ) , + .spoci_sda_oe_o (spoci_sda_oe_o ) + `endif + ) ; + +// pci data io multiplexer inputs +wire pci_mux_tar_ad_en_in = pciu_pciif_ad_en_out ; +wire pci_mux_tar_ad_en_reg_in = out_bckp_tar_ad_en_out ; +wire [31:0] pci_mux_tar_ad_in = pciu_pciif_ad_out ; +wire pci_mux_devsel_in = pciu_pciif_devsel_out ; +wire pci_mux_devsel_en_in = pciu_pciif_devsel_en_out ; +wire pci_mux_trdy_in = pciu_pciif_trdy_out ; +wire pci_mux_trdy_en_in = pciu_pciif_trdy_en_out ; +wire pci_mux_stop_in = pciu_pciif_stop_out ; +wire pci_mux_stop_en_in = pciu_pciif_stop_en_out ; +wire pci_mux_tar_load_in = pciu_ad_load_out ; +wire pci_mux_tar_load_on_transfer_in = pciu_ad_load_on_transfer_out ; + +wire pci_mux_mas_ad_en_in = wbu_pciif_ad_en_out ; +wire [31:0] pci_mux_mas_ad_in = wbu_pciif_ad_out ; + +wire pci_mux_frame_in = wbu_pciif_frame_out ; +wire pci_mux_frame_en_in = wbu_pciif_frame_en_out ; +wire pci_mux_irdy_in = wbu_pciif_irdy_out; +wire pci_mux_irdy_en_in = wbu_pciif_irdy_en_out; +wire pci_mux_mas_load_in = wbu_ad_load_out ; +wire pci_mux_mas_load_on_transfer_in = wbu_ad_load_on_transfer_out ; +wire [3:0] pci_mux_cbe_in = wbu_pciif_cbe_out ; +wire pci_mux_cbe_en_in = wbu_pciif_cbe_en_out ; + +wire pci_mux_par_in = parchk_pci_par_out ; +wire pci_mux_par_en_in = parchk_pci_par_en_out ; +wire pci_mux_perr_in = parchk_pci_perr_out ; +wire pci_mux_perr_en_in = parchk_pci_perr_en_out ; +wire pci_mux_serr_in = parchk_pci_serr_out ; +wire pci_mux_serr_en_in = parchk_pci_serr_en_out; + +wire pci_mux_req_in = wbu_pciif_req_out ; +wire pci_mux_frame_load_in = wbu_pciif_frame_load_out ; + +wire pci_mux_pci_irdy_in = int_pci_irdy ; +wire pci_mux_pci_trdy_in = int_pci_trdy ; +wire pci_mux_pci_frame_in = int_pci_frame ; +wire pci_mux_pci_stop_in = int_pci_stop ; + +wire pci_mux_init_complete_in = conf_pci_init_complete_out ; + +pci_io_mux pci_io_mux +( + .reset_in (reset), + .clk_in (pci_clk), + .frame_in (pci_mux_frame_in), + .frame_en_in (pci_mux_frame_en_in), + .frame_load_in (pci_mux_frame_load_in), + .irdy_in (pci_mux_irdy_in), + .irdy_en_in (pci_mux_irdy_en_in), + .devsel_in (pci_mux_devsel_in), + .devsel_en_in (pci_mux_devsel_en_in), + .trdy_in (pci_mux_trdy_in), + .trdy_en_in (pci_mux_trdy_en_in), + .stop_in (pci_mux_stop_in), + .stop_en_in (pci_mux_stop_en_in), + .master_load_in (pci_mux_mas_load_in), + .master_load_on_transfer_in (pci_mux_mas_load_on_transfer_in), + .target_load_in (pci_mux_tar_load_in), + .target_load_on_transfer_in (pci_mux_tar_load_on_transfer_in), + .cbe_in (pci_mux_cbe_in), + .cbe_en_in (pci_mux_cbe_en_in), + .mas_ad_in (pci_mux_mas_ad_in), + .tar_ad_in (pci_mux_tar_ad_in), + + .mas_ad_en_in (pci_mux_mas_ad_en_in), + .tar_ad_en_in (pci_mux_tar_ad_en_in), + .tar_ad_en_reg_in (pci_mux_tar_ad_en_reg_in), + + .par_in (pci_mux_par_in), + .par_en_in (pci_mux_par_en_in), + .perr_in (pci_mux_perr_in), + .perr_en_in (pci_mux_perr_en_in), + .serr_in (pci_mux_serr_in), + .serr_en_in (pci_mux_serr_en_in), + + .frame_en_out (pci_mux_frame_en_out), + .irdy_en_out (pci_mux_irdy_en_out), + .devsel_en_out (pci_mux_devsel_en_out), + .trdy_en_out (pci_mux_trdy_en_out), + .stop_en_out (pci_mux_stop_en_out), + .cbe_en_out (pci_mux_cbe_en_out), + .ad_en_out (pci_mux_ad_en_out), + + .frame_out (pci_mux_frame_out), + .irdy_out (pci_mux_irdy_out), + .devsel_out (pci_mux_devsel_out), + .trdy_out (pci_mux_trdy_out), + .stop_out (pci_mux_stop_out), + .cbe_out (pci_mux_cbe_out), + .ad_out (pci_mux_ad_out), + .ad_load_out (pci_mux_ad_load_out), + + .par_out (pci_mux_par_out), + .par_en_out (pci_mux_par_en_out), + .perr_out (pci_mux_perr_out), + .perr_en_out (pci_mux_perr_en_out), + .serr_out (pci_mux_serr_out), + .serr_en_out (pci_mux_serr_en_out), + .req_in (pci_mux_req_in), + .req_out (pci_mux_req_out), + .req_en_out (pci_mux_req_en_out), + .pci_irdy_in (pci_mux_pci_irdy_in), + .pci_trdy_in (pci_mux_pci_trdy_in), + .pci_frame_in (pci_mux_pci_frame_in), + .pci_stop_in (pci_mux_pci_stop_in), + .ad_en_unregistered_out (pci_mux_ad_en_unregistered_out), + + .init_complete_in (pci_mux_init_complete_in) +); + +pci_cur_out_reg output_backup +( + .reset_in (reset), + .clk_in (pci_clk), + .frame_in (pci_mux_frame_in), + .frame_en_in (pci_mux_frame_en_in), + .frame_load_in (pci_mux_frame_load_in), + .irdy_in (pci_mux_irdy_in), + .irdy_en_in (pci_mux_irdy_en_in), + .devsel_in (pci_mux_devsel_in), + .trdy_in (pci_mux_trdy_in), + .trdy_en_in (pci_mux_trdy_en_in), + .stop_in (pci_mux_stop_in), + .ad_load_in (pci_mux_ad_load_out), + .cbe_in (pci_mux_cbe_in), + .cbe_en_in (pci_mux_cbe_en_in), + .mas_ad_in (pci_mux_mas_ad_in), + .tar_ad_in (pci_mux_tar_ad_in), + + .mas_ad_en_in (pci_mux_mas_ad_en_in), + .tar_ad_en_in (pci_mux_tar_ad_en_in), + .ad_en_unregistered_in (pci_mux_ad_en_unregistered_out), + + .par_in (pci_mux_par_in), + .par_en_in (pci_mux_par_en_in), + .perr_in (pci_mux_perr_in), + .perr_en_in (pci_mux_perr_en_in), + .serr_in (pci_mux_serr_in), + .serr_en_in (pci_mux_serr_en_in), + + .frame_out (out_bckp_frame_out), + .frame_en_out (out_bckp_frame_en_out), + .irdy_out (out_bckp_irdy_out), + .irdy_en_out (out_bckp_irdy_en_out), + .devsel_out (out_bckp_devsel_out), + .trdy_out (out_bckp_trdy_out), + .trdy_en_out (out_bckp_trdy_en_out), + .stop_out (out_bckp_stop_out), + .cbe_out (out_bckp_cbe_out), + .ad_out (out_bckp_ad_out), + .ad_en_out (out_bckp_ad_en_out), + .cbe_en_out (out_bckp_cbe_en_out), + .tar_ad_en_out (out_bckp_tar_ad_en_out), + .mas_ad_en_out (out_bckp_mas_ad_en_out), + + .par_out (out_bckp_par_out), + .par_en_out (out_bckp_par_en_out), + .perr_out (out_bckp_perr_out), + .perr_en_out (out_bckp_perr_en_out), + .serr_out (out_bckp_serr_out), + .serr_en_out (out_bckp_serr_en_out) +) ; + +// PARITY CHECKER INPUTS +wire parchk_pci_par_in = int_pci_par ; +wire parchk_pci_perr_in = int_pci_perr ; +wire parchk_pci_frame_reg_in = in_reg_frame_out ; +wire parchk_pci_frame_en_in = out_bckp_frame_en_out ; +wire parchk_pci_irdy_en_in = out_bckp_irdy_en_out ; +wire parchk_pci_irdy_reg_in = in_reg_irdy_out ; +wire parchk_pci_trdy_reg_in = in_reg_trdy_out ; + + +wire parchk_pci_trdy_en_in = out_bckp_trdy_en_out ; + + +wire [31:0] parchk_pci_ad_out_in = out_bckp_ad_out ; +wire [31:0] parchk_pci_ad_reg_in = in_reg_ad_out ; +wire [3:0] parchk_pci_cbe_in_in = int_pci_cbe ; +wire [3:0] parchk_pci_cbe_reg_in = in_reg_cbe_out ; +wire [3:0] parchk_pci_cbe_out_in = out_bckp_cbe_out ; +wire parchk_pci_ad_en_in = out_bckp_ad_en_out ; +wire parchk_par_err_response_in = conf_perr_response_out ; +wire parchk_serr_enable_in = conf_serr_enable_out ; + +wire parchk_pci_perr_out_in = out_bckp_perr_out ; +wire parchk_pci_serr_en_in = out_bckp_serr_en_out ; +wire parchk_pci_serr_out_in = out_bckp_serr_out ; +wire parchk_pci_cbe_en_in = out_bckp_cbe_en_out ; + +wire parchk_pci_par_en_in = out_bckp_par_en_out ; + +pci_parity_check parity_checker +( + .reset_in (reset), + .clk_in (pci_clk), + .pci_par_in (parchk_pci_par_in), + .pci_par_out (parchk_pci_par_out), + .pci_par_en_out (parchk_pci_par_en_out), + .pci_par_en_in (parchk_pci_par_en_in), + .pci_perr_in (parchk_pci_perr_in), + .pci_perr_out (parchk_pci_perr_out), + .pci_perr_en_out (parchk_pci_perr_en_out), + .pci_perr_out_in (parchk_pci_perr_out_in), + .pci_serr_out (parchk_pci_serr_out), + .pci_serr_out_in (parchk_pci_serr_out_in), + .pci_serr_en_out (parchk_pci_serr_en_out), + .pci_serr_en_in (parchk_pci_serr_en_in), + .pci_frame_reg_in (parchk_pci_frame_reg_in), + .pci_frame_en_in (parchk_pci_frame_en_in), + .pci_irdy_en_in (parchk_pci_irdy_en_in), + .pci_irdy_reg_in (parchk_pci_irdy_reg_in), + .pci_trdy_reg_in (parchk_pci_trdy_reg_in), + .pci_trdy_en_in (parchk_pci_trdy_en_in), + .pci_ad_out_in (parchk_pci_ad_out_in), + .pci_ad_reg_in (parchk_pci_ad_reg_in), + .pci_cbe_in_in (parchk_pci_cbe_in_in), + .pci_cbe_reg_in (parchk_pci_cbe_reg_in), + .pci_cbe_en_in (parchk_pci_cbe_en_in), + .pci_cbe_out_in (parchk_pci_cbe_out_in), + .pci_ad_en_in (parchk_pci_ad_en_in), + .par_err_response_in (parchk_par_err_response_in), + .par_err_detect_out (parchk_par_err_detect_out), + .perr_mas_detect_out (parchk_perr_mas_detect_out), + .serr_enable_in (parchk_serr_enable_in), + .sig_serr_out (parchk_sig_serr_out) +); + +wire in_reg_gnt_in = pci_gnt_i ; +wire in_reg_frame_in = int_pci_frame ; +wire in_reg_irdy_in = int_pci_irdy ; +wire in_reg_trdy_in = int_pci_trdy ; +wire in_reg_stop_in = int_pci_stop ; +wire in_reg_devsel_in = int_pci_devsel ; +wire in_reg_idsel_in = pci_idsel_i ; +wire [31:0] in_reg_ad_in = pci_ad_i ; +wire [3:0] in_reg_cbe_in = int_pci_cbe ; + +pci_in_reg input_register +( + .reset_in (reset), + .clk_in (pci_clk), + .init_complete_in (conf_pci_init_complete_out), + + .pci_gnt_in (in_reg_gnt_in), + .pci_frame_in (in_reg_frame_in), + .pci_irdy_in (in_reg_irdy_in), + .pci_trdy_in (in_reg_trdy_in), + .pci_stop_in (in_reg_stop_in), + .pci_devsel_in (in_reg_devsel_in), + .pci_idsel_in (in_reg_idsel_in), + .pci_ad_in (in_reg_ad_in), + .pci_cbe_in (in_reg_cbe_in), + + .pci_gnt_reg_out (in_reg_gnt_out), + .pci_frame_reg_out (in_reg_frame_out), + .pci_irdy_reg_out (in_reg_irdy_out), + .pci_trdy_reg_out (in_reg_trdy_out), + .pci_stop_reg_out (in_reg_stop_out), + .pci_devsel_reg_out (in_reg_devsel_out), + .pci_idsel_reg_out (in_reg_idsel_out), + .pci_ad_reg_out (in_reg_ad_out), + .pci_cbe_reg_out (in_reg_cbe_out) +); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v new file mode 100644 index 000000000..2041b046d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "cbe_en_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_cbe_en_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// this one is included in master state machine for CBE output enable driving + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_cbe_en_crit +( + pci_cbe_en_out, + cbe_en_slow_in, + cbe_en_keep_in, + pci_stop_in, + pci_trdy_in +) ; + +output pci_cbe_en_out ; +input cbe_en_slow_in, + cbe_en_keep_in, + pci_stop_in, + pci_trdy_in ; + +assign pci_cbe_en_out = cbe_en_slow_in || cbe_en_keep_in && pci_stop_in && pci_trdy_in ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v new file mode 100644 index 000000000..96ef75556 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "conf_cyc_addr_dec.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_conf_cyc_addr_dec.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + + +// module is a simple decoder which decodes device num field of configuration address +// for type0 configuration cycles. If type 1 configuration cycle is +// initiated then address goes through unchanged + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_conf_cyc_addr_dec +( + ccyc_addr_in, + ccyc_addr_out +) ; + +input [31:0] ccyc_addr_in ; +output [31:0] ccyc_addr_out ; +reg [31:11] ccyc_addr_31_11 ; + +// lower 11 address lines are alweys going through unchanged +assign ccyc_addr_out = {ccyc_addr_31_11, ccyc_addr_in[10:0]} ; + +// configuration cycle type indicator +wire ccyc_type = ccyc_addr_in[0] ; + +always@(ccyc_addr_in or ccyc_type) +begin + if (ccyc_type) + // type 1 cycle - address goes through unchanged + ccyc_addr_31_11 = ccyc_addr_in[31:11] ; + else + begin + // type 0 conf. cycle - decode device number field to appropriate value + case (ccyc_addr_in[15:11]) + 5'h00:ccyc_addr_31_11 = 21'h00_0001 ; + 5'h01:ccyc_addr_31_11 = 21'h00_0002 ; + 5'h02:ccyc_addr_31_11 = 21'h00_0004 ; + 5'h03:ccyc_addr_31_11 = 21'h00_0008 ; + 5'h04:ccyc_addr_31_11 = 21'h00_0010 ; + 5'h05:ccyc_addr_31_11 = 21'h00_0020 ; + 5'h06:ccyc_addr_31_11 = 21'h00_0040 ; + 5'h07:ccyc_addr_31_11 = 21'h00_0080 ; + 5'h08:ccyc_addr_31_11 = 21'h00_0100 ; + 5'h09:ccyc_addr_31_11 = 21'h00_0200 ; + 5'h0A:ccyc_addr_31_11 = 21'h00_0400 ; + 5'h0B:ccyc_addr_31_11 = 21'h00_0800 ; + 5'h0C:ccyc_addr_31_11 = 21'h00_1000 ; + 5'h0D:ccyc_addr_31_11 = 21'h00_2000 ; + 5'h0E:ccyc_addr_31_11 = 21'h00_4000 ; + 5'h0F:ccyc_addr_31_11 = 21'h00_8000 ; + 5'h10:ccyc_addr_31_11 = 21'h01_0000 ; + 5'h11:ccyc_addr_31_11 = 21'h02_0000 ; + 5'h12:ccyc_addr_31_11 = 21'h04_0000 ; + 5'h13:ccyc_addr_31_11 = 21'h08_0000 ; + 5'h14:ccyc_addr_31_11 = 21'h10_0000 ; + default: ccyc_addr_31_11 = 21'h00_0000 ; + endcase + end +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v new file mode 100644 index 000000000..4c806ee8a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v @@ -0,0 +1,3932 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_conf_space.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - tadej@opencores.org //// +//// - Tadej Markovic //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_conf_space.v,v $ +// Revision 1.10 2004/08/19 16:04:53 mihad +// Removed some unused signals. +// +// Revision 1.9 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.8 2004/07/07 12:45:01 mihad +// Added SubsystemVendorID, SubsystemID, MAXLatency, MinGnt defines. +// Enabled value loading from serial EEPROM for all of the above + VendorID and DeviceID registers. +// +// Revision 1.7 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.6 2003/12/28 09:54:48 fr2201 +// def_wb_imagex_addr_map defined correctly +// +// Revision 1.5 2003/12/28 09:20:00 fr2201 +// Reset values for PCI, WB defined (PCI_TAx,WB_BAx,WB_TAx,WB_AMx,WB_BAx_MEM_IO) +// +// Revision 1.4 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.3 2003/08/14 13:06:02 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// Revision 1.2 2003/03/26 13:16:18 mihad +// Added the reset value parameter to the synchronizer flop module. +// Added resets to all synchronizer flop instances. +// Repaired initial sync value in fifos. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.4 2002/08/13 11:03:53 mihad +// Added a few testcases. Repaired wrong reset value for PCI_AM5 register. Repaired Parity Error Detected bit setting. Changed PCI_AM0 to always enabled(regardles of PCI_AM0 define), if image 0 is used as configuration image +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +/*----------------------------------------------------------------------------------------------------------- + w_ prefix is a sign for Write (and read) side of Dual-Port registers + r_ prefix is a sign for Read only side of Dual-Port registers +In the first line there are DATA and ADDRESS ports, in the second line there are write enable and read +enable signals with chip-select (conf_hit) for config. space. +In the third line there are output signlas from Command register of the PCI configuration header !!! +In the fourth line there are input signals to Status register of the PCI configuration header !!! +In the fifth line there is output from Latency Timer & r_Interrupt pin registers of the PCI conf. header !!! +Following are IMAGE specific registers, from which PCI_BASE_ADDR registers are the same as base address +registers from the PCI conf. header !!! +-----------------------------------------------------------------------------------------------------------*/ + // normal R/W address, data and control +module pci_conf_space + ( w_conf_address_in, w_conf_data_in, w_conf_data_out, r_conf_address_in, r_conf_data_out, + w_we_i, w_re, r_re, w_byte_en_in, w_clock, reset, pci_clk, wb_clk, + // outputs from command register of the PCI header + serr_enable, perr_response, pci_master_enable, memory_space_enable, io_space_enable, + // inputs to status register of the PCI header + perr_in, serr_in, master_abort_recv, target_abort_recv, target_abort_set, master_data_par_err, + // output from cache_line_size, latency timer and r_interrupt_pin register of the PCI header + cache_line_size_to_pci, cache_line_size_to_wb, cache_lsize_not_zero_to_wb, + latency_tim, + // output from all pci IMAGE registers + pci_base_addr0, pci_base_addr1, pci_base_addr2, pci_base_addr3, pci_base_addr4, pci_base_addr5, + pci_memory_io0, pci_memory_io1, pci_memory_io2, pci_memory_io3, pci_memory_io4, pci_memory_io5, + pci_addr_mask0, pci_addr_mask1, pci_addr_mask2, pci_addr_mask3, pci_addr_mask4, pci_addr_mask5, + pci_tran_addr0, pci_tran_addr1, pci_tran_addr2, pci_tran_addr3, pci_tran_addr4, pci_tran_addr5, + pci_img_ctrl0, pci_img_ctrl1, pci_img_ctrl2, pci_img_ctrl3, pci_img_ctrl4, pci_img_ctrl5, + // input to pci error control and status register, error address and error data registers + pci_error_be, pci_error_bc, pci_error_rty_exp, pci_error_es, pci_error_sig, pci_error_addr, + pci_error_data, + // output from all wishbone IMAGE registers + wb_base_addr0, wb_base_addr1, wb_base_addr2, wb_base_addr3, wb_base_addr4, wb_base_addr5, + wb_memory_io0, wb_memory_io1, wb_memory_io2, wb_memory_io3, wb_memory_io4, wb_memory_io5, + wb_addr_mask0, wb_addr_mask1, wb_addr_mask2, wb_addr_mask3, wb_addr_mask4, wb_addr_mask5, + wb_tran_addr0, wb_tran_addr1, wb_tran_addr2, wb_tran_addr3, wb_tran_addr4, wb_tran_addr5, + wb_img_ctrl0, wb_img_ctrl1, wb_img_ctrl2, wb_img_ctrl3, wb_img_ctrl4, wb_img_ctrl5, + // input to wb error control and status register, error address and error data registers + wb_error_be, wb_error_bc, wb_error_rty_exp, wb_error_es, wb_error_sig, wb_error_addr, wb_error_data, + // output from conf. cycle generation register (sddress), int. control register & interrupt output + config_addr, icr_soft_res, int_out, + // input to interrupt status register + isr_sys_err_int, isr_par_err_int, isr_int_prop, + + pci_init_complete_out, wb_init_complete_out + + `ifdef PCI_CPCI_HS_IMPLEMENT + , + pci_cpci_hs_enum_oe_o, pci_cpci_hs_led_oe_o, pci_cpci_hs_es_i + `endif + + `ifdef PCI_SPOCI + , + spoci_scl_oe_o, spoci_sda_i, spoci_sda_oe_o + `endif + ) ; + + +/*########################################################################################################### +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + Input and output ports + ====================== +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +###########################################################################################################*/ + +// output data +output [31 : 0] w_conf_data_out ; +output [31 : 0] r_conf_data_out ; +reg [31 : 0] w_conf_data_out ; + +`ifdef NO_CNF_IMAGE +`else +reg [31 : 0] r_conf_data_out ; +`endif + +// input data +input [31 : 0] w_conf_data_in ; +wire [31 : 0] w_conf_pdata_reduced ; // reduced data written into PCI image registers +wire [31 : 0] w_conf_wdata_reduced ; // reduced data written into WB image registers +// input address +input [11 : 0] w_conf_address_in ; +input [11 : 0] r_conf_address_in ; +// input control signals +input w_we_i ; +input w_re ; +input r_re ; +input [3 : 0] w_byte_en_in ; +input w_clock ; +input reset ; +input pci_clk ; +input wb_clk ; +// PCI header outputs from command register +output serr_enable ; +output perr_response ; +output pci_master_enable ; +output memory_space_enable ; +output io_space_enable ; +// PCI header inputs to status register +input perr_in ; +input serr_in ; +input master_abort_recv ; +input target_abort_recv ; +input target_abort_set ; +input master_data_par_err ; +// PCI header output from cache_line_size, latency timer and interrupt pin +output [7 : 0] cache_line_size_to_pci ; // sinchronized to PCI clock +output [7 : 0] cache_line_size_to_wb ; // sinchronized to WB clock +output cache_lsize_not_zero_to_wb ; // used in WBU and PCIU +output [7 : 0] latency_tim ; +//output [2 : 0] int_pin ; // only 3 LSbits are important! +// PCI output from image registers +`ifdef GUEST + output [31:12] pci_base_addr0 ; +`endif + +`ifdef HOST + `ifdef NO_CNF_IMAGE + output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr0 ; + `else + output [31:12] pci_base_addr0 ; + `endif +`endif + +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr1 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr2 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr3 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr4 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_base_addr5 ; +output pci_memory_io0 ; +output pci_memory_io1 ; +output pci_memory_io2 ; +output pci_memory_io3 ; +output pci_memory_io4 ; +output pci_memory_io5 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask0 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask1 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask2 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask3 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask4 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_addr_mask5 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr0 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr1 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr2 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr3 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr4 ; +output [31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] pci_tran_addr5 ; +output [2 : 1] pci_img_ctrl0 ; +output [2 : 1] pci_img_ctrl1 ; +output [2 : 1] pci_img_ctrl2 ; +output [2 : 1] pci_img_ctrl3 ; +output [2 : 1] pci_img_ctrl4 ; +output [2 : 1] pci_img_ctrl5 ; +// PCI input to pci error control and status register, error address and error data registers +input [3 : 0] pci_error_be ; +input [3 : 0] pci_error_bc ; +input pci_error_rty_exp ; +input pci_error_es ; +input pci_error_sig ; +input [31 : 0] pci_error_addr ; +input [31 : 0] pci_error_data ; +// WISHBONE output from image registers +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr0 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr1 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr2 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr3 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr4 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_base_addr5 ; +output wb_memory_io0 ; +output wb_memory_io1 ; +output wb_memory_io2 ; +output wb_memory_io3 ; +output wb_memory_io4 ; +output wb_memory_io5 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask0 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask1 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask2 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask3 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask4 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_addr_mask5 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr0 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr1 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr2 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr3 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr4 ; +output [31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] wb_tran_addr5 ; +output [2 : 0] wb_img_ctrl0 ; +output [2 : 0] wb_img_ctrl1 ; +output [2 : 0] wb_img_ctrl2 ; +output [2 : 0] wb_img_ctrl3 ; +output [2 : 0] wb_img_ctrl4 ; +output [2 : 0] wb_img_ctrl5 ; +// WISHBONE input to wb error control and status register, error address and error data registers +input [3 : 0] wb_error_be ; +input [3 : 0] wb_error_bc ; +input wb_error_rty_exp ; +input wb_error_es ; +input wb_error_sig ; +input [31 : 0] wb_error_addr ; +input [31 : 0] wb_error_data ; +// GENERAL output from conf. cycle generation register & int. control register +output [23 : 0] config_addr ; +output icr_soft_res ; +output int_out ; +// GENERAL input to interrupt status register +input isr_sys_err_int ; +input isr_par_err_int ; +input isr_int_prop ; + +output pci_init_complete_out ; +output wb_init_complete_out ; + +`ifdef PCI_CPCI_HS_IMPLEMENT +output pci_cpci_hs_enum_oe_o ; +output pci_cpci_hs_led_oe_o ; +input pci_cpci_hs_es_i ; + +reg pci_cpci_hs_enum_oe_o ; +reg pci_cpci_hs_led_oe_o ; + +// set the hot swap ejector switch debounce counter width +// it is only 4 for simulation purposes +`ifdef PCI_CPCI_SIM + + parameter hs_es_cnt_width = 4 ; + +`else + + `ifdef PCI33 + + parameter hs_es_cnt_width = 16 ; + + `endif + + `ifdef PCI66 + + parameter hs_es_cnt_width = 17 ; + + `endif +`endif + +`endif + +`ifdef PCI_SPOCI +output spoci_scl_oe_o ; +input spoci_sda_i ; +output spoci_sda_oe_o ; + +reg spoci_cs_nack, + spoci_cs_write, + spoci_cs_read; + +reg [10: 0] spoci_cs_adr ; +reg [ 7: 0] spoci_cs_dat ; +`endif + +/*########################################################################################################### +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + REGISTERS definition + ==================== +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +###########################################################################################################*/ + +// Decoded Register Select signals for writting (only one address decoder) +reg [56 : 0] w_reg_select_dec ; + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +PCI CONFIGURATION SPACE HEADER (type 00h) registers + + BIST and some other registers are not implemented and therefor written in correct + place with comment line. There are also some registers with NOT all bits implemented and therefor uses + _bitX or _bitX2_X1 to sign which bit or range of bits are implemented. + Some special cases and examples are described below! +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +/*----------------------------------------------------------------------------------------------------------- +[000h-00Ch] First 4 DWORDs (32-bit) of PCI configuration header - the same regardless of the HEADER type ! + r_ prefix is a sign for read only registers + Vendor_ID is an ID for a specific vendor defined by PCI_SIG - 2321h does not belong to anyone (e.g. + Xilinx's Vendor_ID is 10EEh and Altera's Vendor_ID is 1172h). Device_ID and Revision_ID should be used + together by application. Class_Code has 3 bytes to define BASE class (06h for PCI Bridge), SUB class + (00h for HOST type, 80h for Other Bridge type) and Interface type (00h for normal). +-----------------------------------------------------------------------------------------------------------*/ + reg [15: 0] r_vendor_id ; + reg [15: 0] r_device_id ; + reg [15: 0] r_subsys_vendor_id ; + reg [15: 0] r_subsys_id ; + + reg command_bit8 ; + reg command_bit6 ; + reg [2 : 0] command_bit2_0 ; + reg [15 : 11] status_bit15_11 ; + parameter r_status_bit10_9 = 2'b01 ; // 2'b01 means MEDIUM devsel timing !!! + reg status_bit8 ; + parameter r_status_bit7 = 1'b1 ; // xfast back-to-back capable response !!! + parameter r_status_bit5 = `HEADER_66MHz ; // 1'b0 indicates 33 MHz capable !!! + +`ifdef PCI_CPCI_HS_IMPLEMENT + wire r_status_bit4 = 1 ; + reg hs_ins ; + reg hs_ext ; + wire [ 1: 0] hs_pi = 2'b00 ; + reg hs_loo ; + reg hs_eim ; + wire [ 7: 0] hs_cap_id = 8'h06 ; + reg hs_ins_armed ; + reg hs_ext_armed ; +`else + wire r_status_bit4 = 0 ; +`endif + + reg [ 7: 0] r_revision_id ; + +`ifdef HOST + parameter r_class_code = 24'h06_00_00 ; +`else + parameter r_class_code = 24'h06_80_00 ; +`endif + reg [7 : 0] cache_line_size_reg ; + reg [7 : 0] latency_timer ; + parameter r_header_type = 8'h00 ; + // REG bist NOT implemented !!! + +/*----------------------------------------------------------------------------------------------------------- +[010h-03Ch] all other DWORDs (32-bit) of PCI configuration header - only for HEADER type 00h ! + r_ prefix is a sign for read only registers + BASE_ADDRESS_REGISTERS are the same as ones in the PCI Target configuration registers section. They + are duplicated and therefor defined just ones and used with the same name as written below. If + IMAGEx is NOT defined there is only parameter image_X assigned to '0' and this parameter is used + elsewhere in the code. This parameter is defined in the INTERNAL SIGNALS part !!! + Interrupt_Pin value 8'h01 is used for INT_A pin used. + MIN_GNT and MAX_LAT are used for device's desired values for Latency Timer value. The value in boath + registers specifies a period of time in units of 1/4 microsecond. ZERO indicates that there are no + major requirements for the settings of Latency Timer. + MIN_GNT specifieshow how long a burst period the device needs at 33MHz. MAX_LAT specifies how often + the device needs to gain access to the PCI bus. Values are choosen assuming that the target does not + insert any wait states. Follow the expamle of settings for simple display card. + If we use 64 (32-bit) FIFO locations for one burst then we need 8 x 1/4 microsecond periods at 33MHz + clock rate => MIN_GNT = 08h ! Resolution is 1024 x 768 (= 786432 pixels for one frame) with 16-bit + color mode. We can transfere 2 16-bit pixels in one FIFO location. From that we calculate, that for + one frame we need 6144 burst transferes in 1/25 second. So we need one burst every 6,51 microsecond + and that is 26 x 1/4 microsecond or 1Ah x 1/4 microsecond => MAX_LAT = 1Ah ! +-----------------------------------------------------------------------------------------------------------*/ + // REG x 6 base_address_register_X IMPLEMENTED as pci_ba_X !!! + // REG r_cardbus_cis_pointer NOT implemented !!! + // REG r_subsystem_vendor_id NOT implemented !!! + // REG r_subsystem_id NOT implemented !!! + // REG r_expansion_rom_base_address NOT implemented !!! + // REG r_cap_list_pointer NOT implemented !!! + reg [7 : 0] interrupt_line ; + parameter r_interrupt_pin = 8'h01 ; + reg [7 : 0] r_min_gnt ; + reg [7 : 0] r_max_lat ; + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +PCI Target configuration registers + There are also some registers with NOT all bits implemented and therefor uses _bitX or _bitX2_X1 to + sign which bit or range of bits are implemented. Some special cases and examples are described below! +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +/*----------------------------------------------------------------------------------------------------------- +[100h-168h] + Depending on defines (PCI_IMAGE1 or .. or PCI_IMAGE5 or (PCI_IMAGE0 and HOST)) in constants.v file, + there are registers corresponding to each IMAGE defined to REG and parameter pci_image_X assigned to '1'. + The maximum number of images is "6". By default there are first two images used and the first (PCI_IMAGE0) + is assigned to Configuration space! With a 'define' PCI_IMAGEx you choose the number of used PCI IMAGES + in a bridge without PCI_IMAGE0 (e.g. PCI_IMAGE3 tells, that PCI_IMAGE1, PCI_IMAGE2 and PCI_IMAGE3 are + used for mapping the space from WB to PCI. Offcourse, PCI_IMAGE0 is assigned to Configuration space). + That leave us PCI_IMAGE5 as the maximum number of images. + There is one exeption, when the core is implemented as HOST. If so, then the PCI specification allowes + the Configuration space NOT to be visible on the PCI bus. With `define PCI_IMAGE0 (and `define HOST), we + assign PCI_IMAGE0 to normal WB to PCI image and not to configuration space! + + When error occurs, PCI ERR_ADDR and ERR_DATA registers stores address and data on the bus that + caused error. While ERR_CS register stores Byte Enables and Bus Command in the MSByte. In bits 10 + and 8 it reports Retry Counter Expired (for posted writes), Error Source (Master Abort) and Error + Report Signal (signals that error has occured) respectively. With bit 0 we enable Error Reporting + mechanism. +-----------------------------------------------------------------------------------------------------------*/ +`ifdef HOST + `ifdef NO_CNF_IMAGE + `ifdef PCI_IMAGE0 // if PCI bridge is HOST and IMAGE0 is assigned as general image space + reg [31 : 8] pci_ba0_bit31_8 ; + reg [2 : 1] pci_img_ctrl0_bit2_1 ; + reg pci_ba0_bit0 ; + reg [31 : 8] pci_am0 ; + reg [31 : 8] pci_ta0 ; + `else // if PCI bridge is HOST and IMAGE0 is not used + wire [31 : 8] pci_ba0_bit31_8 = 24'h0000_00 ; // NO base address needed + wire [2 : 1] pci_img_ctrl0_bit2_1 = 2'b00 ; // NO addr.transl. and pre-fetch + wire pci_ba0_bit0 = 0 ; // config. space is MEMORY space + wire [31 : 8] pci_am0 = 24'h0000_00 ; // NO address mask needed + wire [31 : 8] pci_ta0 = 24'h0000_00 ; // NO address translation needed + `endif + `else // if PCI bridge is HOST and IMAGE0 is assigned to PCI configuration space + reg [31 : 8] pci_ba0_bit31_8 ; + wire [2 : 1] pci_img_ctrl0_bit2_1 = 2'b00 ; // NO pre-fetch and read line support + wire pci_ba0_bit0 = 0 ; // config. space is MEMORY space + wire [31 : 8] pci_am0 = 24'hFFFF_F0 ; // address mask for configuration image always 20'hffff_f + wire [31 : 8] pci_ta0 = 24'h0000_00 ; // NO address translation needed + `endif +`endif + +`ifdef GUEST // if PCI bridge is GUEST, then IMAGE0 is assigned to PCI configuration space + reg [31 : 8] pci_ba0_bit31_8 ; + wire [2 : 1] pci_img_ctrl0_bit2_1 = 2'b00 ; // NO addr.transl. and pre-fetch + wire pci_ba0_bit0 = 0 ; // config. space is MEMORY space + wire [31 : 8] pci_am0 = 24'hffff_f0 ; // address mask for configuration image always 24'hffff_f0 - 4KB mem image + wire [31 : 8] pci_ta0 = 24'h0000_00 ; // NO address translation needed +`endif + +// IMAGE1 is included by default, meanwhile other IMAGEs are optional !!! + reg [2 : 1] pci_img_ctrl1_bit2_1 ; + reg [31 : 8] pci_ba1_bit31_8 ; + `ifdef HOST + reg pci_ba1_bit0 ; + `else + wire pci_ba1_bit0 = `PCI_BA1_MEM_IO ; + `endif + reg [31 : 8] pci_am1 ; + reg [31 : 8] pci_ta1 ; +`ifdef PCI_IMAGE2 + reg [2 : 1] pci_img_ctrl2_bit2_1 ; + reg [31 : 8] pci_ba2_bit31_8 ; + `ifdef HOST + reg pci_ba2_bit0 ; + `else + wire pci_ba2_bit0 = `PCI_BA2_MEM_IO ; + `endif + reg [31 : 8] pci_am2 ; + reg [31 : 8] pci_ta2 ; +`else + wire [2 : 1] pci_img_ctrl2_bit2_1 = 2'b00 ; + wire [31 : 8] pci_ba2_bit31_8 = 24'h0000_00 ; + wire pci_ba2_bit0 = 1'b0 ; + wire [31 : 8] pci_am2 = 24'h0000_00 ; + wire [31 : 8] pci_ta2 = 24'h0000_00 ; +`endif +`ifdef PCI_IMAGE3 + reg [2 : 1] pci_img_ctrl3_bit2_1 ; + reg [31 : 8] pci_ba3_bit31_8 ; + `ifdef HOST + reg pci_ba3_bit0 ; + `else + wire pci_ba3_bit0 = `PCI_BA3_MEM_IO ; + `endif + reg [31 : 8] pci_am3 ; + reg [31 : 8] pci_ta3 ; +`else + wire [2 : 1] pci_img_ctrl3_bit2_1 = 2'b00 ; + wire [31 : 8] pci_ba3_bit31_8 = 24'h0000_00 ; + wire pci_ba3_bit0 = 1'b0 ; + wire [31 : 8] pci_am3 = 24'h0000_00 ; + wire [31 : 8] pci_ta3 = 24'h0000_00 ; +`endif +`ifdef PCI_IMAGE4 + reg [2 : 1] pci_img_ctrl4_bit2_1 ; + reg [31 : 8] pci_ba4_bit31_8 ; + `ifdef HOST + reg pci_ba4_bit0 ; + `else + wire pci_ba4_bit0 = `PCI_BA4_MEM_IO ; + `endif + reg [31 : 8] pci_am4 ; + reg [31 : 8] pci_ta4 ; +`else + wire [2 : 1] pci_img_ctrl4_bit2_1 = 2'b00 ; + wire [31 : 8] pci_ba4_bit31_8 = 24'h0000_00 ; + wire pci_ba4_bit0 = 1'b0 ; + wire [31 : 8] pci_am4 = 24'h0000_00 ; + wire [31 : 8] pci_ta4 = 24'h0000_00 ; +`endif +`ifdef PCI_IMAGE5 + reg [2 : 1] pci_img_ctrl5_bit2_1 ; + reg [31 : 8] pci_ba5_bit31_8 ; + `ifdef HOST + reg pci_ba5_bit0 ; + `else + wire pci_ba5_bit0 = `PCI_BA5_MEM_IO ; + `endif + reg [31 : 8] pci_am5 ; + reg [31 : 8] pci_ta5 ; +`else + wire [2 : 1] pci_img_ctrl5_bit2_1 = 2'b00 ; + wire [31 : 8] pci_ba5_bit31_8 = 24'h0000_00 ; + wire pci_ba5_bit0 = 1'b0 ; + wire [31 : 8] pci_am5 = 24'h0000_00 ; + wire [31 : 8] pci_ta5 = 24'h0000_00 ; +`endif + reg [31 : 24] pci_err_cs_bit31_24 ; + reg pci_err_cs_bit10 ; + reg pci_err_cs_bit9 ; + reg pci_err_cs_bit8 ; + reg pci_err_cs_bit0 ; + reg [31 : 0] pci_err_addr ; + reg [31 : 0] pci_err_data ; + + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +WISHBONE Slave configuration registers + There are also some registers with NOT all bits implemented and therefor uses _bitX or _bitX2_X1 to + sign which bit or range of bits are implemented. Some special cases and examples are described below! +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +/*----------------------------------------------------------------------------------------------------------- +[800h-85Ch] + Depending on defines (WB_IMAGE1 or .. or WB_IMAGE4 or WB_IMAGE5) in constants.v file, there are + registers corresponding to each IMAGE defined to REG and parameter wb_image_X assigned to '1'. + The maximum number of images is "6". By default there are first two images used and the first (WB_IMAGE0) + is assigned to Configuration space! With a 'define' WB_IMAGEx you choose the number of used WB IMAGES in + a bridge without WB_IMAGE0 (e.g. WB_IMAGE3 tells, that WB_IMAGE1, WB_IMAGE2 and WB_IMAGE3 are used for + mapping the space from PCI to WB. Offcourse, WB_IMAGE0 is assigned to Configuration space). That leave + us WB_IMAGE5 as the maximum number of images. + + When error occurs, WISHBONE ERR_ADDR and ERR_DATA registers stores address and data on the bus that + caused error. While ERR_CS register stores Byte Enables and Bus Command in the MSByte. In bits 10, 9 + and 8 it reports Retry Counter Expired (for posted writes), Error Source (Master Abort) and Error + Report Signal (signals that error has occured) respectively. With bit 0 we enable Error Reporting + mechanism. +-----------------------------------------------------------------------------------------------------------*/ +// WB_IMAGE0 is always assigned to config. space or is not used + wire [2 : 0] wb_img_ctrl0_bit2_0 = 3'b000 ; // NO addr.transl., pre-fetch and read-line + wire [31 : 12] wb_ba0_bit31_12 = `WB_CONFIGURATION_BASE ; + wire wb_ba0_bit0 = 0 ; // config. space is MEMORY space + wire [31 : 12] wb_am0 = `WB_AM0 ; // 4KBytes of configuration space is minimum + wire [31 : 12] wb_ta0 = 20'h0000_0 ; // NO address translation needed +// WB_IMAGE1 is included by default meanwhile others are optional ! + reg [2 : 0] wb_img_ctrl1_bit2_0 ; + reg [31 : 12] wb_ba1_bit31_12 ; + reg wb_ba1_bit0 ; + reg [31 : 12] wb_am1 ; + reg [31 : 12] wb_ta1 ; +`ifdef WB_IMAGE2 + reg [2 : 0] wb_img_ctrl2_bit2_0 ; + reg [31 : 12] wb_ba2_bit31_12 ; + reg wb_ba2_bit0 ; + reg [31 : 12] wb_am2 ; + reg [31 : 12] wb_ta2 ; +`else + wire [2 : 0] wb_img_ctrl2_bit2_0 = 3'b000 ; + wire [31 : 12] wb_ba2_bit31_12 = 20'h0000_0 ; + wire wb_ba2_bit0 = 1'b0 ; + wire [31 : 12] wb_am2 = 20'h0000_0 ; + wire [31 : 12] wb_ta2 = 20'h0000_0 ; +`endif +`ifdef WB_IMAGE3 + reg [2 : 0] wb_img_ctrl3_bit2_0 ; + reg [31 : 12] wb_ba3_bit31_12 ; + reg wb_ba3_bit0 ; + reg [31 : 12] wb_am3 ; + reg [31 : 12] wb_ta3 ; +`else + wire [2 : 0] wb_img_ctrl3_bit2_0 = 3'b000 ; + wire [31 : 12] wb_ba3_bit31_12 = 20'h0000_0 ; + wire wb_ba3_bit0 = 1'b0 ; + wire [31 : 12] wb_am3 = 20'h0000_0 ; + wire [31 : 12] wb_ta3 = 20'h0000_0 ; +`endif +`ifdef WB_IMAGE4 + reg [2 : 0] wb_img_ctrl4_bit2_0 ; + reg [31 : 12] wb_ba4_bit31_12 ; + reg wb_ba4_bit0 ; + reg [31 : 12] wb_am4 ; + reg [31 : 12] wb_ta4 ; +`else + wire [2 : 0] wb_img_ctrl4_bit2_0 = 3'b000 ; + wire [31 : 12] wb_ba4_bit31_12 = 20'h0000_0 ; + wire wb_ba4_bit0 = 1'b0 ; + wire [31 : 12] wb_am4 = 20'h0000_0 ; + wire [31 : 12] wb_ta4 = 20'h0000_0 ; +`endif +`ifdef WB_IMAGE5 + reg [2 : 0] wb_img_ctrl5_bit2_0 ; + reg [31 : 12] wb_ba5_bit31_12 ; + reg wb_ba5_bit0 ; + reg [31 : 12] wb_am5 ; + reg [31 : 12] wb_ta5 ; +`else + wire [2 : 0] wb_img_ctrl5_bit2_0 = 3'b000 ; + wire [31 : 12] wb_ba5_bit31_12 = 20'h0000_0 ; + wire wb_ba5_bit0 = 1'b0 ; + wire [31 : 12] wb_am5 = 20'h0000_0 ; + wire [31 : 12] wb_ta5 = 20'h0000_0 ; +`endif + reg [31 : 24] wb_err_cs_bit31_24 ; +/* reg wb_err_cs_bit10 ;*/ + reg wb_err_cs_bit9 ; + reg wb_err_cs_bit8 ; + reg wb_err_cs_bit0 ; + reg [31 : 0] wb_err_addr ; + reg [31 : 0] wb_err_data ; + + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +Configuration Cycle address register + There are also some registers with NOT all bits implemented and therefor uses _bitX or _bitX2_X1 to + sign which bit or range of bits are implemented. +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +/*----------------------------------------------------------------------------------------------------------- +[860h-868h] + PCI bridge must ignore Type 1 configuration cycles (Master Abort) since they are used for PCI to PCI + bridges. This is single function device, that means responding on configuration cycles to all functions + (or responding only to function 0). Configuration address register for generating configuration cycles + is prepared for all options (it includes Bus Number, Device, Function, Offset and Type). + Interrupt acknowledge register stores interrupt vector data returned during Interrupt Acknowledge cycle. +-----------------------------------------------------------------------------------------------------------*/ +`ifdef HOST + reg [23 : 2] cnf_addr_bit23_2 ; + reg cnf_addr_bit0 ; +`else // GUEST + wire [23 : 2] cnf_addr_bit23_2 = 22'h0 ; + wire cnf_addr_bit0 = 1'b0 ; +`endif + // reg [31 : 0] cnf_data ; IMPLEMENTED elsewhere !!!!! + // reg [31 : 0] int_ack ; IMPLEMENTED elsewhere !!!!! + + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +General Interrupt registers + There are also some registers with NOT all bits implemented and therefor uses _bitX or _bitX2_X1 to + sign which bit or range of bits are implemented. +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +/*----------------------------------------------------------------------------------------------------------- +[FF8h-FFCh] + Bit 31 in the Interrupt Control register is set by software and used to generate SOFT RESET. Other 4 + bits are used to enable interrupt generations. + 5 LSbits in the Interrupt Status register are indicating System Error Int, Parity Error Int, PCI & WB + Error Int and Inerrupt respecively. System and Parity errors are implented only in HOST bridge + implementations! +-----------------------------------------------------------------------------------------------------------*/ + reg icr_bit31 ; +`ifdef HOST + reg [4 : 3] icr_bit4_3 ; + reg [4 : 3] isr_bit4_3 ; + reg [2 : 0] icr_bit2_0 ; + reg [2 : 0] isr_bit2_0 ; +`else // GUEST + wire [4 : 3] icr_bit4_3 = 2'h0 ; + wire [4 : 3] isr_bit4_3 = 2'h0 ; + reg [2 : 0] icr_bit2_0 ; + reg [2 : 0] isr_bit2_0 ; +`endif + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- +Initialization complete identifier + When using I2C or similar initialisation mechanism, + the bridge must not respond to transaction requests on PCI bus, + not even to configuration cycles. + Therefore, only when init_complete is set, the bridge starts + participating on the PCI bus as an active device. + Two additional flip flops are also provided for GUEST implementation, + to synchronize to the pci clock after PCI reset is asynchronously de-asserted. +------------------------------------------------------------------------------------------------------------- +###########################################################################################################*/ + +`ifdef GUEST + +reg rst_inactive_sync ; +reg rst_inactive ; + +`else + +wire rst_inactive = 1'b1 ; + +`endif + +reg init_complete ; + +wire sync_init_complete ; + +`ifdef HOST +assign wb_init_complete_out = init_complete ; + +pci_synchronizer_flop #(1, 0) i_pci_init_complete_sync +( + .data_in ( init_complete ), + .clk_out ( pci_clk ), + .sync_data_out ( sync_init_complete ), + .async_reset ( reset ) +); + +reg pci_init_complete_out ; + +always@(posedge pci_clk or posedge reset) +begin + if (reset) + pci_init_complete_out <= 1'b0 ; + else + pci_init_complete_out <= sync_init_complete ; +end + +`endif + +`ifdef GUEST + +assign pci_init_complete_out = init_complete ; + +pci_synchronizer_flop #(1, 0) i_wb_init_complete_sync +( + .data_in ( init_complete ), + .clk_out ( wb_clk ), + .sync_data_out ( sync_init_complete ), + .async_reset ( reset ) +); + +reg wb_init_complete_out ; + +always@(posedge wb_clk or posedge reset) +begin + if (reset) + wb_init_complete_out <= 1'b0 ; + else + wb_init_complete_out <= sync_init_complete ; +end + +`endif + +/*########################################################################################################### +------------------------------------------------------------------------------------------------------------- + + +-----------------------------------------------------------------------------------------------------------*/ + +`ifdef NO_CNF_IMAGE // if IMAGE0 is assigned as general image space + + assign r_conf_data_out = 32'h0000_0000 ; + +`else + + always@(r_conf_address_in or + status_bit15_11 or status_bit8 or r_status_bit4 or command_bit8 or command_bit6 or command_bit2_0 or + latency_timer or cache_line_size_reg or r_vendor_id or r_device_id or r_revision_id or + r_subsys_vendor_id or r_subsys_id or r_max_lat or r_min_gnt or + pci_ba0_bit31_8 or + pci_img_ctrl0_bit2_1 or pci_am0 or pci_ta0 or pci_ba0_bit0 or + pci_img_ctrl1_bit2_1 or pci_am1 or pci_ta1 or pci_ba1_bit31_8 or pci_ba1_bit0 or + pci_img_ctrl2_bit2_1 or pci_am2 or pci_ta2 or pci_ba2_bit31_8 or pci_ba2_bit0 or + pci_img_ctrl3_bit2_1 or pci_am3 or pci_ta3 or pci_ba3_bit31_8 or pci_ba3_bit0 or + pci_img_ctrl4_bit2_1 or pci_am4 or pci_ta4 or pci_ba4_bit31_8 or pci_ba4_bit0 or + pci_img_ctrl5_bit2_1 or pci_am5 or pci_ta5 or pci_ba5_bit31_8 or pci_ba5_bit0 or + interrupt_line or + pci_err_cs_bit31_24 or pci_err_cs_bit10 or pci_err_cs_bit9 or pci_err_cs_bit8 or pci_err_cs_bit0 or + pci_err_addr or pci_err_data or + wb_ba0_bit31_12 or wb_ba0_bit0 or + wb_img_ctrl1_bit2_0 or wb_ba1_bit31_12 or wb_ba1_bit0 or wb_am1 or wb_ta1 or + wb_img_ctrl2_bit2_0 or wb_ba2_bit31_12 or wb_ba2_bit0 or wb_am2 or wb_ta2 or + wb_img_ctrl3_bit2_0 or wb_ba3_bit31_12 or wb_ba3_bit0 or wb_am3 or wb_ta3 or + wb_img_ctrl4_bit2_0 or wb_ba4_bit31_12 or wb_ba4_bit0 or wb_am4 or wb_ta4 or + wb_img_ctrl5_bit2_0 or wb_ba5_bit31_12 or wb_ba5_bit0 or wb_am5 or wb_ta5 or + wb_err_cs_bit31_24 or /*wb_err_cs_bit10 or*/ wb_err_cs_bit9 or wb_err_cs_bit8 or wb_err_cs_bit0 or + wb_err_addr or wb_err_data or + cnf_addr_bit23_2 or cnf_addr_bit0 or icr_bit31 or icr_bit4_3 or icr_bit2_0 or isr_bit4_3 or isr_bit2_0 + + `ifdef PCI_CPCI_HS_IMPLEMENT + or hs_ins or hs_ext or hs_pi or hs_loo or hs_eim or hs_cap_id + `endif + + `ifdef PCI_SPOCI + or spoci_cs_nack or spoci_cs_write or spoci_cs_read or spoci_cs_adr or spoci_cs_dat + `endif + ) + begin + case (r_conf_address_in[9:2]) + // PCI header - configuration space + 8'h0: r_conf_data_out = { r_device_id, r_vendor_id } ; + 8'h1: r_conf_data_out = { status_bit15_11, r_status_bit10_9, status_bit8, r_status_bit7, 1'h0, r_status_bit5, r_status_bit4, + 4'h0, 7'h00, command_bit8, 1'h0, command_bit6, 3'h0, command_bit2_0 } ; + 8'h2: r_conf_data_out = { r_class_code, r_revision_id } ; + 8'h3: r_conf_data_out = { 8'h00, r_header_type, latency_timer, cache_line_size_reg } ; + 8'h4: + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba0_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba0_bit0 & pci_am0[31]; + `else + r_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + r_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + end + 8'h5: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba1_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba1_bit0 & pci_am1[31]; + end + 8'h6: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba2_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba2_bit0 & pci_am2[31]; + end + 8'h7: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba3_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba3_bit0 & pci_am3[31]; + end + 8'h8: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba4_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba4_bit0 & pci_am4[31]; + end + 8'h9: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba5_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba5_bit0 & pci_am5[31]; + end + 8'hB: + begin + r_conf_data_out = {r_subsys_id, r_subsys_vendor_id} ; + end + `ifdef PCI_CPCI_HS_IMPLEMENT + 8'hD: + begin + r_conf_data_out = {24'h0000_00, `PCI_CAP_PTR_VAL} ; + end + `endif + 8'hf: r_conf_data_out = { r_max_lat, r_min_gnt, r_interrupt_pin, interrupt_line } ; + `ifdef PCI_CPCI_HS_IMPLEMENT + (`PCI_CAP_PTR_VAL >> 2): + begin + r_conf_data_out = {8'h00, hs_ins, hs_ext, hs_pi, hs_loo, 1'b0, hs_eim, 1'b0, 8'h00, hs_cap_id} ; + end + `endif + // PCI target - configuration space + {2'b01, `P_IMG_CTRL0_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl0_bit2_1, 1'h0 } ; + {2'b01, `P_BA0_ADDR} : + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba0_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba0_bit0 & pci_am0[31]; + `else + r_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + r_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + end + {2'b01, `P_AM0_ADDR}: + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + `else + r_conf_data_out[31:12] = pci_am0[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + r_conf_data_out[31:12] = pci_am0[31:12] ; + r_conf_data_out[11: 0] = 12'h000 ; + `endif + end + {2'b01, `P_TA0_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_IMG_CTRL1_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl1_bit2_1, 1'h0 } ; + {2'b01, `P_BA1_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba1_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba1_bit0 & pci_am1[31]; + end + {2'b01, `P_AM1_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_TA1_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_IMG_CTRL2_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl2_bit2_1, 1'h0 } ; + {2'b01, `P_BA2_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba2_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba2_bit0 & pci_am2[31]; + end + {2'b01, `P_AM2_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_TA2_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_IMG_CTRL3_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl3_bit2_1, 1'h0 } ; + {2'b01, `P_BA3_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba3_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba3_bit0 & pci_am3[31]; + end + {2'b01, `P_AM3_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_TA3_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_IMG_CTRL4_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl4_bit2_1, 1'h0 } ; + {2'b01, `P_BA4_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba4_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba4_bit0 & pci_am4[31]; + end + {2'b01, `P_AM4_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_TA4_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_IMG_CTRL5_ADDR}: r_conf_data_out = { 29'h00000000, pci_img_ctrl5_bit2_1, 1'h0 } ; + {2'b01, `P_BA5_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba5_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = pci_ba5_bit0 & pci_am5[31]; + end + {2'b01, `P_AM5_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_TA5_ADDR}: + begin + r_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `P_ERR_CS_ADDR}: r_conf_data_out = { pci_err_cs_bit31_24, 13'h0000, pci_err_cs_bit10, pci_err_cs_bit9, + pci_err_cs_bit8, 7'h00, pci_err_cs_bit0 } ; + {2'b01, `P_ERR_ADDR_ADDR}: r_conf_data_out = pci_err_addr ; + {2'b01, `P_ERR_DATA_ADDR}: r_conf_data_out = pci_err_data ; + // WB slave - configuration space + {2'b01, `WB_CONF_SPC_BAR_ADDR}: r_conf_data_out = { wb_ba0_bit31_12, 11'h000, wb_ba0_bit0 } ; + {2'b01, `W_IMG_CTRL1_ADDR}: r_conf_data_out = { 29'h00000000, wb_img_ctrl1_bit2_0 } ; + {2'b01, `W_BA1_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba1_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = wb_ba1_bit0 ; + end + {2'b01, `W_AM1_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_TA1_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_IMG_CTRL2_ADDR}: r_conf_data_out = { 29'h00000000, wb_img_ctrl2_bit2_0 } ; + `W_BA2_ADDR : + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba2_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = wb_ba2_bit0 ; + end + {2'b01, `W_AM2_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_TA2_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_IMG_CTRL3_ADDR}: r_conf_data_out = { 29'h00000000, wb_img_ctrl3_bit2_0 } ; + {2'b01, `W_BA3_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba3_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = wb_ba3_bit0 ; + end + {2'b01, `W_AM3_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_TA3_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_IMG_CTRL4_ADDR}: r_conf_data_out = { 29'h00000000, wb_img_ctrl4_bit2_0 } ; + {2'b01, `W_BA4_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba4_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = wb_ba4_bit0 ; + end + {2'b01, `W_AM4_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_TA4_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_IMG_CTRL5_ADDR}: r_conf_data_out = { 29'h00000000, wb_img_ctrl5_bit2_0 } ; + {2'b01, `W_BA5_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba5_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + r_conf_data_out[0] = wb_ba5_bit0 ; + end + {2'b01, `W_AM5_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_TA5_ADDR}: + begin + r_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + r_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + end + {2'b01, `W_ERR_CS_ADDR}: r_conf_data_out = { wb_err_cs_bit31_24, /*13*/14'h0000, /*wb_err_cs_bit10,*/ + wb_err_cs_bit9, wb_err_cs_bit8, 7'h00, wb_err_cs_bit0 } ; + {2'b01, `W_ERR_ADDR_ADDR}: r_conf_data_out = wb_err_addr ; + {2'b01, `W_ERR_DATA_ADDR}: r_conf_data_out = wb_err_data ; + + {2'b01, `CNF_ADDR_ADDR}: r_conf_data_out = { 8'h00, cnf_addr_bit23_2, 1'h0, cnf_addr_bit0 } ; + // `CNF_DATA_ADDR: implemented elsewhere !!! + // `INT_ACK_ADDR : implemented elsewhere !!! + {2'b01, `ICR_ADDR}: r_conf_data_out = { icr_bit31, 26'h0000_000, icr_bit4_3, icr_bit2_0 } ; + {2'b01, `ISR_ADDR}: r_conf_data_out = { 27'h0000_000, isr_bit4_3, isr_bit2_0 } ; + + `ifdef PCI_SPOCI + 8'hff: r_conf_data_out = {spoci_cs_nack, 5'h0, spoci_cs_write, spoci_cs_read, + 5'h0, spoci_cs_adr[10:8], + spoci_cs_adr[7:0], + spoci_cs_dat[7:0]} ; + `endif + default : r_conf_data_out = 32'h0000_0000 ; + endcase + end + +`endif + +`ifdef PCI_SPOCI +reg [ 7: 0] spoci_reg_num ; +wire [11: 0] w_conf_address = init_complete ? w_conf_address_in : {2'b00, spoci_reg_num, 2'b00} ; +`else +wire [11: 0] w_conf_address = w_conf_address_in ; +wire [ 7: 0] spoci_reg_num = 'hff ; +`endif + +always@(w_conf_address or + status_bit15_11 or status_bit8 or r_status_bit4 or command_bit8 or command_bit6 or command_bit2_0 or + latency_timer or cache_line_size_reg or r_vendor_id or r_device_id or r_revision_id or + r_subsys_id or r_subsys_vendor_id or r_max_lat or r_min_gnt or + pci_ba0_bit31_8 or + pci_img_ctrl0_bit2_1 or pci_am0 or pci_ta0 or pci_ba0_bit0 or + pci_img_ctrl1_bit2_1 or pci_am1 or pci_ta1 or pci_ba1_bit31_8 or pci_ba1_bit0 or + pci_img_ctrl2_bit2_1 or pci_am2 or pci_ta2 or pci_ba2_bit31_8 or pci_ba2_bit0 or + pci_img_ctrl3_bit2_1 or pci_am3 or pci_ta3 or pci_ba3_bit31_8 or pci_ba3_bit0 or + pci_img_ctrl4_bit2_1 or pci_am4 or pci_ta4 or pci_ba4_bit31_8 or pci_ba4_bit0 or + pci_img_ctrl5_bit2_1 or pci_am5 or pci_ta5 or pci_ba5_bit31_8 or pci_ba5_bit0 or + interrupt_line or + pci_err_cs_bit31_24 or pci_err_cs_bit10 or pci_err_cs_bit9 or pci_err_cs_bit8 or pci_err_cs_bit0 or + pci_err_addr or pci_err_data or + wb_ba0_bit31_12 or wb_ba0_bit0 or + wb_img_ctrl1_bit2_0 or wb_ba1_bit31_12 or wb_ba1_bit0 or wb_am1 or wb_ta1 or + wb_img_ctrl2_bit2_0 or wb_ba2_bit31_12 or wb_ba2_bit0 or wb_am2 or wb_ta2 or + wb_img_ctrl3_bit2_0 or wb_ba3_bit31_12 or wb_ba3_bit0 or wb_am3 or wb_ta3 or + wb_img_ctrl4_bit2_0 or wb_ba4_bit31_12 or wb_ba4_bit0 or wb_am4 or wb_ta4 or + wb_img_ctrl5_bit2_0 or wb_ba5_bit31_12 or wb_ba5_bit0 or wb_am5 or wb_ta5 or + wb_err_cs_bit31_24 or /*wb_err_cs_bit10 or*/ wb_err_cs_bit9 or wb_err_cs_bit8 or wb_err_cs_bit0 or + wb_err_addr or wb_err_data or + cnf_addr_bit23_2 or cnf_addr_bit0 or icr_bit31 or icr_bit4_3 or icr_bit2_0 or isr_bit4_3 or isr_bit2_0 + + `ifdef PCI_CPCI_HS_IMPLEMENT + or hs_ins or hs_ext or hs_pi or hs_loo or hs_eim or hs_cap_id + `endif + + `ifdef PCI_SPOCI + or spoci_cs_nack or spoci_cs_write or spoci_cs_read or spoci_cs_adr or spoci_cs_dat + `endif + ) +begin + case (w_conf_address[9:2]) + 8'h0: + begin + w_conf_data_out = { r_device_id, r_vendor_id } ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // Read-Only register + end + 8'h1: // w_reg_select_dec bit 0 + begin + w_conf_data_out = { status_bit15_11, r_status_bit10_9, status_bit8, r_status_bit7, 1'h0, r_status_bit5, r_status_bit4, + 4'h0, 7'h00, command_bit8, 1'h0, command_bit6, 3'h0, command_bit2_0 } ; + w_reg_select_dec = 57'h000_0000_0000_0001 ; + end + 8'h2: + begin + w_conf_data_out = { r_class_code, r_revision_id } ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // Read-Only register + end + 8'h3: // w_reg_select_dec bit 1 + begin + w_conf_data_out = { 8'h00, r_header_type, latency_timer, cache_line_size_reg } ; + w_reg_select_dec = 57'h000_0000_0000_0002 ; + end + 8'h4: // w_reg_select_dec bit 4 + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba0_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba0_bit0 & pci_am0[31]; + `else + w_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + w_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + w_reg_select_dec = 57'h000_0000_0000_0010 ; // The same for another address + end + 8'h5: // w_reg_select_dec bit 8 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba1_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba1_bit0 & pci_am1[31]; + w_reg_select_dec = 57'h000_0000_0000_0100 ; // The same for another address + end + 8'h6: // w_reg_select_dec bit 12 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba2_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba2_bit0 & pci_am2[31]; + w_reg_select_dec = 57'h000_0000_0000_1000 ; // The same for another address + end + 8'h7: // w_reg_select_dec bit 16 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba3_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba3_bit0 & pci_am3[31]; + w_reg_select_dec = 57'h000_0000_0001_0000 ; // The same for another address + end + 8'h8: // w_reg_select_dec bit 20 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba4_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba4_bit0 & pci_am4[31]; + w_reg_select_dec = 57'h000_0000_0010_0000 ; // The same for another address + end + 8'h9: // w_reg_select_dec bit 24 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba5_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba5_bit0 & pci_am5[31]; + w_reg_select_dec = 57'h000_0000_0100_0000 ; // The same for another address + end + 8'hB: + begin + w_conf_data_out = {r_subsys_id, r_subsys_vendor_id} ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; + end + +`ifdef PCI_CPCI_HS_IMPLEMENT + 8'hD: + begin + w_conf_data_out = {24'h0000_00, `PCI_CAP_PTR_VAL} ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // Read-Only register + end +`endif + 8'hf: // w_reg_select_dec bit 2 + begin + w_conf_data_out = { r_max_lat, r_min_gnt, r_interrupt_pin, interrupt_line } ; + w_reg_select_dec = 57'h000_0000_0000_0004 ; + end +`ifdef PCI_CPCI_HS_IMPLEMENT + (`PCI_CAP_PTR_VAL >> 2): + begin + w_reg_select_dec = 57'h100_0000_0000_0000 ; + w_conf_data_out = {8'h00, hs_ins, hs_ext, hs_pi, hs_loo, 1'b0, hs_eim, 1'b0, 8'h00, hs_cap_id} ; + end +`endif + {2'b01, `P_IMG_CTRL0_ADDR}: // w_reg_select_dec bit 3 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl0_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0000_0008 ; + end + {2'b01, `P_BA0_ADDR}: // w_reg_select_dec bit 4 + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba0_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba0_bit0 & pci_am0[31]; + `else + w_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + w_conf_data_out[31:12] = pci_ba0_bit31_8[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + w_reg_select_dec = 57'h000_0000_0000_0010 ; // The same for another address + end + {2'b01, `P_AM0_ADDR}: // w_reg_select_dec bit 5 + begin + `ifdef HOST + `ifdef NO_CNF_IMAGE + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + `else + w_conf_data_out[31:12] = pci_am0[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + `endif + + `ifdef GUEST + w_conf_data_out[31:12] = pci_am0[31:12] ; + w_conf_data_out[11: 0] = 12'h000 ; + `endif + w_reg_select_dec = 57'h000_0000_0000_0020 ; + end + {2'b01, `P_TA0_ADDR}: // w_reg_select_dec bit 6 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0000_0040 ; + end + {2'b01, `P_IMG_CTRL1_ADDR}: // w_reg_select_dec bit 7 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl1_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0000_0080 ; + end + {2'b01, `P_BA1_ADDR}: // w_reg_select_dec bit 8 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba1_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba1_bit0 & pci_am1[31]; + w_reg_select_dec = 57'h000_0000_0000_0100 ; // The same for another address + end + {2'b01, `P_AM1_ADDR}: // w_reg_select_dec bit 9 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0000_0200 ; + end + {2'b01, `P_TA1_ADDR}: // w_reg_select_dec bit 10 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0000_0400 ; + end + {2'b01, `P_IMG_CTRL2_ADDR}: // w_reg_select_dec bit 11 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl2_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0000_0800 ; + end + {2'b01, `P_BA2_ADDR}: // w_reg_select_dec bit 12 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba2_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba2_bit0 & pci_am2[31]; + w_reg_select_dec = 57'h000_0000_0000_1000 ; // The same for another address + end + {2'b01, `P_AM2_ADDR}: // w_reg_select_dec bit 13 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0000_2000 ; + end + {2'b01, `P_TA2_ADDR}: // w_reg_select_dec bit 14 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0000_4000 ; + end + {2'b01, `P_IMG_CTRL3_ADDR}: // w_reg_select_dec bit 15 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl3_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0000_8000 ; + end + {2'b01, `P_BA3_ADDR}: // w_reg_select_dec bit 16 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba3_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba3_bit0 & pci_am3[31]; + w_reg_select_dec = 57'h000_0000_0001_0000 ; // The same for another address + end + {2'b01, `P_AM3_ADDR}: // w_reg_select_dec bit 17 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0002_0000 ; + end + {2'b01, `P_TA3_ADDR}: // w_reg_select_dec bit 18 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0004_0000 ; + end + {2'b01, `P_IMG_CTRL4_ADDR}: // w_reg_select_dec bit 19 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl4_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0008_0000 ; + end + {2'b01, `P_BA4_ADDR}: // w_reg_select_dec bit 20 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba4_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba4_bit0 & pci_am4[31]; + w_reg_select_dec = 57'h000_0000_0010_0000 ; // The same for another address + end + {2'b01, `P_AM4_ADDR}: // w_reg_select_dec bit 21 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0020_0000 ; + end + {2'b01, `P_TA4_ADDR}: // w_reg_select_dec bit 22 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0040_0000 ; + end + {2'b01, `P_IMG_CTRL5_ADDR}: // w_reg_select_dec bit 23 + begin + w_conf_data_out = { 29'h00000000, pci_img_ctrl5_bit2_1, 1'h0 } ; + w_reg_select_dec = 57'h000_0000_0080_0000 ; + end + {2'b01, `P_BA5_ADDR}: // w_reg_select_dec bit 24 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ba5_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] & + pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = pci_ba5_bit0 & pci_am5[31]; + w_reg_select_dec = 57'h000_0000_0100_0000 ; // The same for another address + end + {2'b01, `P_AM5_ADDR}: // w_reg_select_dec bit 25 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0200_0000 ; + end + {2'b01, `P_TA5_ADDR}: // w_reg_select_dec bit 26 + begin + w_conf_data_out[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = pci_ta5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`PCI_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0000_0400_0000 ; + end + {2'b01, `P_ERR_CS_ADDR}: // w_reg_select_dec bit 27 + begin + w_conf_data_out = { pci_err_cs_bit31_24, 13'h0000, pci_err_cs_bit10, pci_err_cs_bit9, + pci_err_cs_bit8, 7'h00, pci_err_cs_bit0 } ; + w_reg_select_dec = 57'h000_0000_0800_0000 ; + end + {2'b01, `P_ERR_ADDR_ADDR}: // w_reg_select_dec bit 28 + begin + w_conf_data_out = pci_err_addr ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // = 56'h00_0000_1000_0000 ; + end + {2'b01, `P_ERR_DATA_ADDR}: // w_reg_select_dec bit 29 + begin + w_conf_data_out = pci_err_data ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // = 56'h00_0000_2000_0000 ; + end + // WB slave - configuration space + {2'b01, `WB_CONF_SPC_BAR_ADDR}: + begin + w_conf_data_out = { wb_ba0_bit31_12, 11'h000, wb_ba0_bit0 } ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; // Read-Only register + end + {2'b01, `W_IMG_CTRL1_ADDR}: // w_reg_select_dec bit 30 + begin + w_conf_data_out = { 29'h00000000, wb_img_ctrl1_bit2_0 } ; + w_reg_select_dec = 57'h000_0000_4000_0000 ; + end + {2'b01, `W_BA1_ADDR}: // w_reg_select_dec bit 31 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba1_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = wb_ba1_bit0 ; + w_reg_select_dec = 57'h000_0000_8000_0000 ; + end + {2'b01, `W_AM1_ADDR}: // w_reg_select_dec bit 32 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0001_0000_0000 ; + end + {2'b01, `W_TA1_ADDR}: // w_reg_select_dec bit 33 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0002_0000_0000 ; + end + {2'b01, `W_IMG_CTRL2_ADDR}: // w_reg_select_dec bit 34 + begin + w_conf_data_out = { 29'h00000000, wb_img_ctrl2_bit2_0 } ; + w_reg_select_dec = 57'h000_0004_0000_0000 ; + end + {2'b01, `W_BA2_ADDR}: // w_reg_select_dec bit 35 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba2_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = wb_ba2_bit0 ; + w_reg_select_dec = 57'h000_0008_0000_0000 ; + end + {2'b01, `W_AM2_ADDR}: // w_reg_select_dec bit 36 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0010_0000_0000 ; + end + {2'b01, `W_TA2_ADDR}: // w_reg_select_dec bit 37 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0020_0000_0000 ; + end + {2'b01, `W_IMG_CTRL3_ADDR}: // w_reg_select_dec bit 38 + begin + w_conf_data_out = { 29'h00000000, wb_img_ctrl3_bit2_0 } ; + w_reg_select_dec = 57'h000_0040_0000_0000 ; + end + {2'b01, `W_BA3_ADDR}: // w_reg_select_dec bit 39 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba3_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = wb_ba3_bit0 ; + w_reg_select_dec = 57'h000_0080_0000_0000 ; + end + {2'b01, `W_AM3_ADDR}: // w_reg_select_dec bit 40 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0100_0000_0000 ; + end + {2'b01, `W_TA3_ADDR}: // w_reg_select_dec bit 41 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_0200_0000_0000 ; + end + {2'b01, `W_IMG_CTRL4_ADDR}: // w_reg_select_dec bit 42 + begin + w_conf_data_out = { 29'h00000000, wb_img_ctrl4_bit2_0 } ; + w_reg_select_dec = 57'h000_0400_0000_0000 ; + end + {2'b01, `W_BA4_ADDR}: // w_reg_select_dec bit 43 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba4_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = wb_ba4_bit0 ; + w_reg_select_dec = 57'h000_0800_0000_0000 ; + end + {2'b01, `W_AM4_ADDR}: // w_reg_select_dec bit 44 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_1000_0000_0000 ; + end + {2'b01, `W_TA4_ADDR}: // w_reg_select_dec bit 45 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h000_2000_0000_0000 ; + end + {2'b01, `W_IMG_CTRL5_ADDR}: // w_reg_select_dec bit 46 + begin + w_conf_data_out = { 29'h00000000, wb_img_ctrl5_bit2_0 } ; + w_reg_select_dec = 57'h000_4000_0000_0000 ; + end + {2'b01, `W_BA5_ADDR}: // w_reg_select_dec bit 47 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ba5_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] & + wb_am5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):1] = 0 ; + w_conf_data_out[0] = wb_ba5_bit0 ; + w_reg_select_dec = 57'h000_8000_0000_0000 ; + end + {2'b01, `W_AM5_ADDR}: // w_reg_select_dec bit 48 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_am5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h001_0000_0000_0000 ; + end + {2'b01, `W_TA5_ADDR}: // w_reg_select_dec bit 49 + begin + w_conf_data_out[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = wb_ta5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; + w_conf_data_out[(31-`WB_NUM_OF_DEC_ADDR_LINES):0] = 0 ; + w_reg_select_dec = 57'h002_0000_0000_0000 ; + end + {2'b01, `W_ERR_CS_ADDR}: // w_reg_select_dec bit 50 + begin + w_conf_data_out = { wb_err_cs_bit31_24, /*13*/14'h0000, /*wb_err_cs_bit10,*/ + wb_err_cs_bit9, wb_err_cs_bit8, 7'h00, wb_err_cs_bit0 } ; + w_reg_select_dec = 57'h004_0000_0000_0000 ; + end + {2'b01, `W_ERR_ADDR_ADDR}: // w_reg_select_dec bit 51 + begin + w_conf_data_out = wb_err_addr ; + w_reg_select_dec = 57'h008_0000_0000_0000 ; + end + {2'b01, `W_ERR_DATA_ADDR}: // w_reg_select_dec bit 52 + begin + w_conf_data_out = wb_err_data ; + w_reg_select_dec = 57'h010_0000_0000_0000 ; + end + {2'b01, `CNF_ADDR_ADDR}: // w_reg_select_dec bit 53 + begin + w_conf_data_out = { 8'h00, cnf_addr_bit23_2, 1'h0, cnf_addr_bit0 } ; + w_reg_select_dec = 57'h020_0000_0000_0000 ; + end + // `CNF_DATA_ADDR: implemented elsewhere !!! + // `INT_ACK_ADDR: implemented elsewhere !!! + {2'b01, `ICR_ADDR}: // w_reg_select_dec bit 54 + begin + w_conf_data_out = { icr_bit31, 26'h0000_000, icr_bit4_3, icr_bit2_0 } ; + w_reg_select_dec = 57'h040_0000_0000_0000 ; + end + {2'b01, `ISR_ADDR}: // w_reg_select_dec bit 55 + begin + w_conf_data_out = { 27'h0000_000, isr_bit4_3, isr_bit2_0 } ; + w_reg_select_dec = 57'h080_0000_0000_0000 ; + end + +`ifdef PCI_SPOCI + 8'hff: + begin + w_conf_data_out = {spoci_cs_nack, 5'h0, spoci_cs_write, spoci_cs_read, + 5'h0, spoci_cs_adr[10:8], + spoci_cs_adr[7:0], + spoci_cs_dat[7:0]} ; + + // this register is implemented separate from other registers, because + // it has special features implemented + w_reg_select_dec = 57'h000_0000_0000_0000 ; + end +`endif + + default: + begin + w_conf_data_out = 32'h0000_0000 ; + w_reg_select_dec = 57'h000_0000_0000_0000 ; + end + endcase +end + +`ifdef PCI_SPOCI +reg init_we ; +reg init_cfg_done ; +reg [31: 0] spoci_dat ; +wire [31: 0] w_conf_data = init_cfg_done ? w_conf_data_in : spoci_dat ; +wire [ 3: 0] w_byte_en = init_cfg_done ? w_byte_en_in : 4'b0000 ; +`else +wire init_we = 1'b0 ; +wire init_cfg_done = 1'b1 ; +wire [31: 0] w_conf_data = w_conf_data_in ; +wire [ 3: 0] w_byte_en = w_byte_en_in ; +wire [31: 0] spoci_dat = 'h0000_0000 ; +`endif + +// Reduced write data for BASE, MASK and TRANSLATION registers of PCI and WB images +assign w_conf_pdata_reduced[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] = w_conf_data[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign w_conf_pdata_reduced[(31-`PCI_NUM_OF_DEC_ADDR_LINES): 0] = 0 ; +assign w_conf_wdata_reduced[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] = w_conf_data[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign w_conf_wdata_reduced[(31-`WB_NUM_OF_DEC_ADDR_LINES): 0] = 0 ; + +wire w_we = w_we_i | init_we ; + +always@(posedge w_clock or posedge reset) +begin + // Here are implemented all registers that are reset with RESET signal otherwise they can be normaly written!!! + // Registers that are commented are implemented after this alwasy statement, because they are e.g. reset with + // RESET signal, set with some status signal and they are erased with writting '1' into them !!! + if (reset) + begin + /*status_bit15_11 ; status_bit8 ;*/ command_bit8 <= 1'h0 ; command_bit6 <= 1'h0 ; command_bit2_0 <= 3'h0 ; + latency_timer <= 8'h00 ; cache_line_size_reg <= 8'h00 ; + // ALL pci_base address registers are the same as pci_baX registers ! + interrupt_line <= 8'h00 ; + + `ifdef HOST + `ifdef NO_CNF_IMAGE // if PCI bridge is HOST and IMAGE0 is assigned as general image space + `ifdef PCI_IMAGE0 + pci_img_ctrl0_bit2_1 <= {`PCI_AT_EN0, 1'b0} ; + pci_ba0_bit31_8 <= 24'h0000_00 ; + pci_ba0_bit0 <= `PCI_BA0_MEM_IO ; + pci_am0 <= `PCI_AM0 ; + pci_ta0 <= `PCI_TA0 ;//fr2201 translation address + `endif + `else + pci_ba0_bit31_8 <= 24'h0000_00 ; + `endif + `endif + + `ifdef GUEST + pci_ba0_bit31_8 <= 24'h0000_00 ; + `endif + + pci_img_ctrl1_bit2_1 <= {`PCI_AT_EN1, 1'b0} ; + + pci_ba1_bit31_8 <= 24'h0000_00 ; + `ifdef HOST + pci_ba1_bit0 <= `PCI_BA1_MEM_IO ; + `endif + pci_am1 <= `PCI_AM1; + pci_ta1 <= `PCI_TA1 ;//FR2201 translation address ; + `ifdef PCI_IMAGE2 + + pci_img_ctrl2_bit2_1 <= {`PCI_AT_EN2, 1'b0} ; + + pci_ba2_bit31_8 <= 24'h0000_00 ; + `ifdef HOST + pci_ba2_bit0 <= `PCI_BA2_MEM_IO ; + `endif + pci_am2 <= `PCI_AM2; + pci_ta2 <= `PCI_TA2 ;//FR2201 translation address ; + `endif + `ifdef PCI_IMAGE3 + + pci_img_ctrl3_bit2_1 <= {`PCI_AT_EN3, 1'b0} ; //FR2201 when defined enabled + + pci_ba3_bit31_8 <= 24'h0000_00 ; + `ifdef HOST + pci_ba3_bit0 <= `PCI_BA3_MEM_IO ; + `endif + pci_am3 <= `PCI_AM3; + pci_ta3 <= `PCI_TA3 ;//FR2201 translation address ; + `endif + `ifdef PCI_IMAGE4 + + pci_img_ctrl4_bit2_1 <= {`PCI_AT_EN4, 1'b0} ; //FR2201 when defined enabled + + pci_ba4_bit31_8 <= 24'h0000_00 ; + `ifdef HOST + pci_ba4_bit0 <= `PCI_BA4_MEM_IO ; + `endif + pci_am4 <= `PCI_AM4; + pci_ta4 <= `PCI_TA4 ;//FR2201 translation address ; + `endif + `ifdef PCI_IMAGE5 + + pci_img_ctrl5_bit2_1 <= {`PCI_AT_EN5, 1'b0} ; //FR2201 when defined enabled + + pci_ba5_bit31_8 <= 24'h0000_00 ; + `ifdef HOST + pci_ba5_bit0 <= `PCI_BA5_MEM_IO ; + `endif + pci_am5 <= `PCI_AM5; //FR2201 pci_am0 + pci_ta5 <= `PCI_TA5 ;//FR2201 translation address ; + `endif + /*pci_err_cs_bit31_24 ; pci_err_cs_bit10; pci_err_cs_bit9 ; pci_err_cs_bit8 ;*/ pci_err_cs_bit0 <= 1'h0 ; + /*pci_err_addr ;*/ + /*pci_err_data ;*/ + // + wb_img_ctrl1_bit2_0 <= {`WB_AT_EN1, 2'b00} ; + + wb_ba1_bit31_12 <=`WB_BA1; //FR2201 Address bar + wb_ba1_bit0 <=`WB_BA1_MEM_IO;// + wb_am1 <= `WB_AM1 ;//FR2201 Address mask + wb_ta1 <= `WB_TA1 ;//FR2201 20'h0000_0 ; + `ifdef WB_IMAGE2 + wb_img_ctrl2_bit2_0 <= {`WB_AT_EN2, 2'b00} ; + + wb_ba2_bit31_12 <=`WB_BA2; //FR2201 Address bar + wb_ba2_bit0 <=`WB_BA2_MEM_IO;// + wb_am2 <=`WB_AM2 ;//FR2201 Address mask + wb_ta2 <=`WB_TA2 ;//FR2201 translation address ; + `endif + `ifdef WB_IMAGE3 + wb_img_ctrl3_bit2_0 <= {`WB_AT_EN3, 2'b00} ; + + wb_ba3_bit31_12 <=`WB_BA3; //FR2201 Address bar + wb_ba3_bit0 <=`WB_BA3_MEM_IO;// + wb_am3 <=`WB_AM3 ;//FR2201 Address mask + wb_ta3 <=`WB_TA3 ;//FR2201 translation address ; + `endif + `ifdef WB_IMAGE4 + wb_img_ctrl4_bit2_0 <= {`WB_AT_EN4, 2'b00} ; + + wb_ba4_bit31_12 <=`WB_BA4; //FR2201 Address bar + wb_ba4_bit0 <=`WB_BA4_MEM_IO;// + wb_am4 <=`WB_AM4 ;//FR2201 Address mask + wb_ta4 <=`WB_TA4 ;//FR2201 translation address ; + `endif + `ifdef WB_IMAGE5 + wb_img_ctrl5_bit2_0 <= {`WB_AT_EN5, 2'b00} ; + + wb_ba5_bit31_12 <=`WB_BA5; //FR2201 Address bar ; + wb_ba5_bit0 <=`WB_BA5_MEM_IO;//FR2201 1'h0 ; + wb_am5 <=`WB_AM5 ;//FR2201 Address mask + wb_ta5 <=`WB_TA5 ;//FR2201 translation address ; + `endif + /*wb_err_cs_bit31_24 ; wb_err_cs_bit10 ; wb_err_cs_bit9 ; wb_err_cs_bit8 ;*/ wb_err_cs_bit0 <= 1'h0 ; + /*wb_err_addr ;*/ + /*wb_err_data ;*/ + + `ifdef HOST + cnf_addr_bit23_2 <= 22'h0000_00 ; cnf_addr_bit0 <= 1'h0 ; + `endif + + icr_bit31 <= 1'h0 ; + `ifdef HOST + icr_bit2_0 <= 3'h0 ; + icr_bit4_3 <= 2'h0 ; + `else + icr_bit2_0[2:0] <= 3'h0 ; + `endif + /*isr_bit4_3 ; isr_bit2_0 ;*/ + + // Not register bit; used only internally after reset! + init_complete <= 1'b0 ; + + `ifdef GUEST + rst_inactive_sync <= 1'b0 ; + rst_inactive <= 1'b0 ; + `endif + + `ifdef PCI_CPCI_HS_IMPLEMENT + /*hs_ins hs_ext*/ hs_loo <= 1'b0; hs_eim <= 1'b0; + // Not register bits; used only internally after reset! + /*hs_ins_armed hs_ext_armed*/ + `endif + end +/* ----------------------------------------------------------------------------------------------------------- +Following register bits should have asynchronous RESET & SET! That is why they are IMPLEMENTED separately +after this ALWAYS block!!! (for every register bit, there are two D-FF implemented) + status_bit15_11[15] <= 1'b1 ; + status_bit15_11[14] <= 1'b1 ; + status_bit15_11[13] <= 1'b1 ; + status_bit15_11[12] <= 1'b1 ; + status_bit15_11[11] <= 1'b1 ; + status_bit8 <= 1'b1 ; + pci_err_cs_bit10 <= 1'b1 ; + pci_err_cs_bit9 <= 1'b1 ; + pci_err_cs_bit8 <= 1'b1 ; + pci_err_cs_bit31_24 <= { pci_error_be, pci_error_bc } ; + pci_err_addr <= pci_error_addr ; + pci_err_data <= pci_error_data ; + wb_err_cs_bit10 <= 1'b1 ; + wb_err_cs_bit9 <= 1'b1 ; + wb_err_cs_bit8 <= 1'b1 ; + wb_err_cs_bit31_24 <= { wb_error_be, wb_error_bc } ; + wb_err_addr <= wb_error_addr ; + wb_err_data <= wb_error_data ; + isr_bit4_0[4] <= 1'b1 & icr_bit4_0[4] ; + isr_bit4_0[3] <= 1'b1 & icr_bit4_0[3] ; + isr_bit4_0[2] <= 1'b1 & icr_bit4_0[2] ; + isr_bit4_0[1] <= 1'b1 & icr_bit4_0[1] ; + isr_bit4_0[0] <= 1'b1 & icr_bit4_0[0] ; + + hs_ins; hs_ext; +-----------------------------------------------------------------------------------------------------------*/ + // Here follows normal writting to registers (only to their valid bits) ! + else + begin + if (w_we) + begin + // PCI header - configuration space + if (w_reg_select_dec[0]) // w_conf_address[5:2] = 4'h1: + begin + if (~w_byte_en[1]) + command_bit8 <= w_conf_data[8] ; + if (~w_byte_en[0]) + begin + command_bit6 <= w_conf_data[6] ; + command_bit2_0 <= w_conf_data[2:0] ; + end + end + if (w_reg_select_dec[1]) // w_conf_address[5:2] = 4'h3: + begin + if (~w_byte_en[1]) + latency_timer <= w_conf_data[15:8] ; + if (~w_byte_en[0]) + cache_line_size_reg <= w_conf_data[7:0] ; + end +// if (w_reg_select_dec[4]) // w_conf_address[5:2] = 4'h4: +// Also used with IMAGE0 + +// if (w_reg_select_dec[8]) // w_conf_address[5:2] = 4'h5: +// Also used with IMAGE1 + +// if (w_reg_select_dec[12]) // w_conf_address[5:2] = 4'h6: +// Also used with IMAGE2 + +// if (w_reg_select_dec[16]) // w_conf_address[5:2] = 4'h7: +// Also used with IMAGE3 + +// if (w_reg_select_dec[20]) // w_conf_address[5:2] = 4'h8: +// Also used with IMAGE4 + +// if (w_reg_select_dec[24]) // w_conf_address[5:2] = 4'h9: +// Also used with IMAGE5 and IMAGE6 + if (w_reg_select_dec[2]) // w_conf_address[5:2] = 4'hf: + begin + if (~w_byte_en[0]) + interrupt_line <= w_conf_data[7:0] ; + end + // PCI target - configuration space +`ifdef HOST + `ifdef NO_CNF_IMAGE + `ifdef PCI_IMAGE0 // if PCI bridge is HOST and IMAGE0 is assigned as general image space + if (w_reg_select_dec[3]) // case (w_conf_address[7:2]) = `P_IMG_CTRL0_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl0_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[4]) // case (w_conf_address[7:2]) = `P_BA0_ADDR: + begin + if (~w_byte_en[3]) + pci_ba0_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba0_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba0_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + if (~w_byte_en[0]) + pci_ba0_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[5]) // case (w_conf_address[7:2]) = `P_AM0_ADDR: + begin + if (~w_byte_en[3]) + pci_am0[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am0[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am0[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[6]) // case (w_conf_address[7:2]) = `P_TA0_ADDR: + begin + if (~w_byte_en[3]) + pci_ta0[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta0[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta0[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + `endif + `else + if (w_reg_select_dec[4]) // case (w_conf_address[7:2]) = `P_BA0_ADDR: + begin + if (~w_byte_en[3]) + pci_ba0_bit31_8[31:24] <= w_conf_data[31:24] ; + if (~w_byte_en[2]) + pci_ba0_bit31_8[23:16] <= w_conf_data[23:16] ; + if (~w_byte_en[1]) + pci_ba0_bit31_8[15:12] <= w_conf_data[15:12] ; + end + `endif +`endif + +`ifdef GUEST + if (w_reg_select_dec[4]) // case (w_conf_address[7:2]) = `P_BA0_ADDR: + begin + if (~w_byte_en[3]) + pci_ba0_bit31_8[31:24] <= w_conf_data[31:24] ; + if (~w_byte_en[2]) + pci_ba0_bit31_8[23:16] <= w_conf_data[23:16] ; + if (~w_byte_en[1]) + pci_ba0_bit31_8[15:12] <= w_conf_data[15:12] ; + end +`endif + if (w_reg_select_dec[7]) // case (w_conf_address[7:2]) = `P_IMG_CTRL1_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl1_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[8]) // case (w_conf_address[7:2]) = `P_BA1_ADDR: + begin + if (~w_byte_en[3]) + pci_ba1_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba1_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba1_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + `ifdef HOST + if (~w_byte_en[0]) + pci_ba1_bit0 <= w_conf_data[0] ; + `endif + end + if (w_reg_select_dec[9]) // case (w_conf_address[7:2]) = `P_AM1_ADDR: + begin + if (~w_byte_en[3]) + pci_am1[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am1[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am1[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[10]) // case (w_conf_address[7:2]) = `P_TA1_ADDR: + begin + if (~w_byte_en[3]) + pci_ta1[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta1[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta1[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end +`ifdef PCI_IMAGE2 + if (w_reg_select_dec[11]) // case (w_conf_address[7:2]) = `P_IMG_CTRL2_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl2_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[12]) // case (w_conf_address[7:2]) = `P_BA2_ADDR: + begin + if (~w_byte_en[3]) + pci_ba2_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba2_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba2_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + `ifdef HOST + if (~w_byte_en[0]) + pci_ba2_bit0 <= w_conf_data[0] ; + `endif + end + if (w_reg_select_dec[13]) // case (w_conf_address[7:2]) = `P_AM2_ADDR: + begin + if (~w_byte_en[3]) + pci_am2[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am2[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am2[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[14]) // case (w_conf_address[7:2]) = `P_TA2_ADDR: + begin + if (~w_byte_en[3]) + pci_ta2[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta2[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta2[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end +`endif +`ifdef PCI_IMAGE3 + if (w_reg_select_dec[15]) // case (w_conf_address[7:2]) = `P_IMG_CTRL3_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl3_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[16]) // case (w_conf_address[7:2]) = `P_BA3_ADDR: + begin + if (~w_byte_en[3]) + pci_ba3_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba3_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba3_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + `ifdef HOST + if (~w_byte_en[0]) + pci_ba3_bit0 <= w_conf_data[0] ; + `endif + end + if (w_reg_select_dec[17]) // case (w_conf_address[7:2]) = `P_AM3_ADDR: + begin + if (~w_byte_en[3]) + pci_am3[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am3[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am3[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[18]) // case (w_conf_address[7:2]) = `P_TA3_ADDR: + begin + if (~w_byte_en[3]) + pci_ta3[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta3[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta3[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end +`endif +`ifdef PCI_IMAGE4 + if (w_reg_select_dec[19]) // case (w_conf_address[7:2]) = `P_IMG_CTRL4_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl4_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[20]) // case (w_conf_address[7:2]) = `P_BA4_ADDR: + begin + if (~w_byte_en[3]) + pci_ba4_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba4_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba4_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + `ifdef HOST + if (~w_byte_en[0]) + pci_ba4_bit0 <= w_conf_data[0] ; + `endif + end + if (w_reg_select_dec[21]) // case (w_conf_address[7:2]) = `P_AM4_ADDR: + begin + if (~w_byte_en[3]) + pci_am4[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am4[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am4[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[22]) // case (w_conf_address[7:2]) = `P_TA4_ADDR: + begin + if (~w_byte_en[3]) + pci_ta4[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta4[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta4[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end +`endif +`ifdef PCI_IMAGE5 + if (w_reg_select_dec[23]) // case (w_conf_address[7:2]) = `P_IMG_CTRL5_ADDR: + begin + if (~w_byte_en[0]) + pci_img_ctrl5_bit2_1 <= w_conf_data[2:1] ; + end + if (w_reg_select_dec[24]) // case (w_conf_address[7:2]) = `P_BA5_ADDR: + begin + if (~w_byte_en[3]) + pci_ba5_bit31_8[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ba5_bit31_8[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ba5_bit31_8[15: 8] <= w_conf_pdata_reduced[15: 8] ; + `ifdef HOST + if (~w_byte_en[0]) + pci_ba5_bit0 <= w_conf_data[0] ; + `endif + end + if (w_reg_select_dec[25]) // case (w_conf_address[7:2]) = `P_AM5_ADDR: + begin + if (~w_byte_en[3]) + pci_am5[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_am5[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_am5[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end + if (w_reg_select_dec[26]) // case (w_conf_address[7:2]) = `P_TA5_ADDR: + begin + if (~w_byte_en[3]) + pci_ta5[31:24] <= w_conf_pdata_reduced[31:24] ; + if (~w_byte_en[2]) + pci_ta5[23:16] <= w_conf_pdata_reduced[23:16] ; + if (~w_byte_en[1]) + pci_ta5[15: 8] <= w_conf_pdata_reduced[15: 8] ; + end +`endif + if (w_reg_select_dec[27]) // case (w_conf_address[7:2]) = `P_ERR_CS_ADDR: + begin + if (~w_byte_en[0]) + pci_err_cs_bit0 <= w_conf_data[0] ; + end + // WB slave - configuration space + if (w_reg_select_dec[30]) // case (w_conf_address[7:2]) = `W_IMG_CTRL1_ADDR: + begin + if (~w_byte_en[0]) + wb_img_ctrl1_bit2_0 <= w_conf_data[2:0] ; + end + if (w_reg_select_dec[31]) // case (w_conf_address[7:2]) = `W_BA1_ADDR: + begin + if (~w_byte_en[3]) + wb_ba1_bit31_12[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ba1_bit31_12[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ba1_bit31_12[15:12] <= w_conf_wdata_reduced[15:12] ; + if (~w_byte_en[0]) + wb_ba1_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[32]) // case (w_conf_address[7:2]) = `W_AM1_ADDR: + begin + if (~w_byte_en[3]) + wb_am1[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_am1[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_am1[15:12] <= w_conf_wdata_reduced[15:12] ; + end + if (w_reg_select_dec[33]) // case (w_conf_address[7:2]) = `W_TA1_ADDR: + begin + if (~w_byte_en[3]) + wb_ta1[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ta1[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ta1[15:12] <= w_conf_wdata_reduced[15:12] ; + end +`ifdef WB_IMAGE2 + if (w_reg_select_dec[34]) // case (w_conf_address[7:2]) = `W_IMG_CTRL2_ADDR: + begin + if (~w_byte_en[0]) + wb_img_ctrl2_bit2_0 <= w_conf_data[2:0] ; + end + if (w_reg_select_dec[35]) // case (w_conf_address[7:2]) = `W_BA2_ADDR: + begin + if (~w_byte_en[3]) + wb_ba2_bit31_12[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ba2_bit31_12[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ba2_bit31_12[15:12] <= w_conf_wdata_reduced[15:12] ; + if (~w_byte_en[0]) + wb_ba2_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[36]) // case (w_conf_address[7:2]) = `W_AM2_ADDR: + begin + if (~w_byte_en[3]) + wb_am2[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_am2[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_am2[15:12] <= w_conf_wdata_reduced[15:12] ; + end + if (w_reg_select_dec[37]) // case (w_conf_address[7:2]) = `W_TA2_ADDR: + begin + if (~w_byte_en[3]) + wb_ta2[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ta2[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ta2[15:12] <= w_conf_wdata_reduced[15:12] ; + end +`endif +`ifdef WB_IMAGE3 + if (w_reg_select_dec[38]) // case (w_conf_address[7:2]) = `W_IMG_CTRL3_ADDR: + begin + if (~w_byte_en[0]) + wb_img_ctrl3_bit2_0 <= w_conf_data[2:0] ; + end + if (w_reg_select_dec[39]) // case (w_conf_address[7:2]) = `W_BA3_ADDR: + begin + if (~w_byte_en[3]) + wb_ba3_bit31_12[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ba3_bit31_12[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ba3_bit31_12[15:12] <= w_conf_wdata_reduced[15:12] ; + if (~w_byte_en[0]) + wb_ba3_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[40]) // case (w_conf_address[7:2]) = `W_AM3_ADDR: + begin + if (~w_byte_en[3]) + wb_am3[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_am3[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_am3[15:12] <= w_conf_wdata_reduced[15:12] ; + end + if (w_reg_select_dec[41]) // case (w_conf_address[7:2]) = `W_TA3_ADDR: + begin + if (~w_byte_en[3]) + wb_ta3[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ta3[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ta3[15:12] <= w_conf_wdata_reduced[15:12] ; + end +`endif +`ifdef WB_IMAGE4 + if (w_reg_select_dec[42]) // case (w_conf_address[7:2]) = `W_IMG_CTRL4_ADDR: + begin + if (~w_byte_en[0]) + wb_img_ctrl4_bit2_0 <= w_conf_data[2:0] ; + end + if (w_reg_select_dec[43]) // case (w_conf_address[7:2]) = `W_BA4_ADDR: + begin + if (~w_byte_en[3]) + wb_ba4_bit31_12[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ba4_bit31_12[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ba4_bit31_12[15:12] <= w_conf_wdata_reduced[15:12] ; + if (~w_byte_en[0]) + wb_ba4_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[44]) // case (w_conf_address[7:2]) = `W_AM4_ADDR: + begin + if (~w_byte_en[3]) + wb_am4[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_am4[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_am4[15:12] <= w_conf_wdata_reduced[15:12] ; + end + if (w_reg_select_dec[45]) // case (w_conf_address[7:2]) = `W_TA4_ADDR: + begin + if (~w_byte_en[3]) + wb_ta4[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ta4[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ta4[15:12] <= w_conf_wdata_reduced[15:12] ; + end +`endif +`ifdef WB_IMAGE5 + if (w_reg_select_dec[46]) // case (w_conf_address[7:2]) = `W_IMG_CTRL5_ADDR: + begin + if (~w_byte_en[0]) + wb_img_ctrl5_bit2_0 <= w_conf_data[2:0] ; + end + if (w_reg_select_dec[47]) // case (w_conf_address[7:2]) = `W_BA5_ADDR: + begin + if (~w_byte_en[3]) + wb_ba5_bit31_12[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ba5_bit31_12[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ba5_bit31_12[15:12] <= w_conf_wdata_reduced[15:12] ; + if (~w_byte_en[0]) + wb_ba5_bit0 <= w_conf_data[0] ; + end + if (w_reg_select_dec[48]) // case (w_conf_address[7:2]) = `W_AM5_ADDR: + begin + if (~w_byte_en[3]) + wb_am5[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_am5[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_am5[15:12] <= w_conf_wdata_reduced[15:12] ; + end + if (w_reg_select_dec[49]) // case (w_conf_address[7:2]) = `W_TA5_ADDR: + begin + if (~w_byte_en[3]) + wb_ta5[31:24] <= w_conf_wdata_reduced[31:24] ; + if (~w_byte_en[2]) + wb_ta5[23:16] <= w_conf_wdata_reduced[23:16] ; + if (~w_byte_en[1]) + wb_ta5[15:12] <= w_conf_wdata_reduced[15:12] ; + end +`endif + if (w_reg_select_dec[50]) // case (w_conf_address[7:2]) = `W_ERR_CS_ADDR: + begin + if (~w_byte_en[0]) + wb_err_cs_bit0 <= w_conf_data[0] ; + end + +`ifdef HOST + if (w_reg_select_dec[53]) // case (w_conf_address[7:2]) = `CNF_ADDR_ADDR: + begin + if (~w_byte_en[2]) + cnf_addr_bit23_2[23:16] <= w_conf_data[23:16] ; + if (~w_byte_en[1]) + cnf_addr_bit23_2[15:8] <= w_conf_data[15:8] ; + if (~w_byte_en[0]) + begin + cnf_addr_bit23_2[7:2] <= w_conf_data[7:2] ; + cnf_addr_bit0 <= w_conf_data[0] ; + end + end +`endif + // `CNF_DATA_ADDR: implemented elsewhere !!! + // `INT_ACK_ADDR : implemented elsewhere !!! + if (w_reg_select_dec[54]) // case (w_conf_address[7:2]) = `ICR_ADDR: + begin + if (~w_byte_en[3]) + icr_bit31 <= w_conf_data[31] ; + + if (~w_byte_en[0]) + begin +`ifdef HOST + icr_bit4_3 <= w_conf_data[4:3] ; + icr_bit2_0 <= w_conf_data[2:0] ; +`else + icr_bit2_0[2:0] <= w_conf_data[2:0] ; +`endif + end + end + +`ifdef PCI_CPCI_HS_IMPLEMENT + if (w_reg_select_dec[56]) + begin + if (~w_byte_en[2]) + begin + hs_loo <= w_conf_data[19]; + hs_eim <= w_conf_data[17]; + end + end +`endif + end // end of we + + // Not register bits; used only internally after reset! + `ifdef GUEST + rst_inactive_sync <= 1'b1 ; + rst_inactive <= rst_inactive_sync ; + `endif + + if (rst_inactive & ~init_complete & init_cfg_done) + init_complete <= 1'b1 ; + end +end + +// implementation of read only device identification registers +always@(posedge w_clock or posedge reset) +begin + if (reset) + begin + r_vendor_id <= `HEADER_VENDOR_ID ; + r_device_id <= `HEADER_DEVICE_ID ; + r_revision_id <= `HEADER_REVISION_ID ; + r_subsys_vendor_id <= `HEADER_SUBSYS_VENDOR_ID ; + r_subsys_id <= `HEADER_SUBSYS_ID ; + r_max_lat <= `HEADER_MAX_LAT ; + r_min_gnt <= `HEADER_MIN_GNT ; + end else + begin + if (init_we) + begin + if (spoci_reg_num == 'h0) + begin + r_vendor_id <= spoci_dat[15: 0] ; + r_device_id <= spoci_dat[31:16] ; + end + + if (spoci_reg_num == 'hB) + begin + r_subsys_vendor_id <= spoci_dat[15: 0] ; + r_subsys_id <= spoci_dat[31:16] ; + end + + if (spoci_reg_num == 'h2) + begin + r_revision_id <= spoci_dat[ 7: 0] ; + end + + if (spoci_reg_num == 'hF) + begin + r_max_lat <= spoci_dat[31:24] ; + r_min_gnt <= spoci_dat[23:16] ; + end + end + end +end + +// This signals are synchronous resets for registers, whic occures when asynchronous RESET is '1' or +// data '1' is synchronously written into them! +reg delete_status_bit15 ; +reg delete_status_bit14 ; +reg delete_status_bit13 ; +reg delete_status_bit12 ; +reg delete_status_bit11 ; +reg delete_status_bit8 ; +reg delete_pci_err_cs_bit8 ; +reg delete_wb_err_cs_bit8 ; +reg delete_isr_bit4 ; +reg delete_isr_bit3 ; +reg delete_isr_bit2 ; +reg delete_isr_bit1 ; + +// This are aditional register bits, which are resets when their value is '1' !!! +always@(w_we or w_reg_select_dec or w_conf_data or w_byte_en) +begin +// I' is written into, then it also sets signals to '1' + delete_status_bit15 = w_conf_data[31] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_status_bit14 = w_conf_data[30] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_status_bit13 = w_conf_data[29] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_status_bit12 = w_conf_data[28] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_status_bit11 = w_conf_data[27] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_status_bit8 = w_conf_data[24] & !w_byte_en[3] & w_we & w_reg_select_dec[0] ; + delete_pci_err_cs_bit8 = w_conf_data[8] & !w_byte_en[1] & w_we & w_reg_select_dec[27] ; + delete_wb_err_cs_bit8 = w_conf_data[8] & !w_byte_en[1] & w_we & w_reg_select_dec[50] ; + delete_isr_bit4 = w_conf_data[4] & !w_byte_en[0] & w_we & w_reg_select_dec[55] ; + delete_isr_bit3 = w_conf_data[3] & !w_byte_en[0] & w_we & w_reg_select_dec[55] ; + delete_isr_bit2 = w_conf_data[2] & !w_byte_en[0] & w_we & w_reg_select_dec[55] ; + delete_isr_bit1 = w_conf_data[1] & !w_byte_en[0] & w_we & w_reg_select_dec[55] ; +end + +// STATUS BITS of PCI Header status register +`ifdef SYNCHRONEOUS_CLOCK_DOMAINS + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[15] <= 1'b0 ; + else + begin + if (perr_in) // Synchronous set + status_bit15_11[15] <= 1'b1 ; + else if (delete_status_bit15) // Synchronous reset + status_bit15_11[15] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[14] <= 1'b0 ; + else + begin + if (serr_in) // Synchronous set + status_bit15_11[14] <= 1'b1 ; + else if (delete_status_bit14) // Synchronous reset + status_bit15_11[14] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[13] <= 1'b0 ; + else + begin + if (master_abort_recv) // Synchronous set + status_bit15_11[13] <= 1'b1 ; + else if (delete_status_bit13) // Synchronous reset + status_bit15_11[13] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[12] <= 1'b0 ; + else + begin + if (target_abort_recv) // Synchronous set + status_bit15_11[12] <= 1'b1 ; + else if (delete_status_bit12) // Synchronous reset + status_bit15_11[12] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[11] <= 1'b0 ; + else + begin + if (target_abort_set) // Synchronous set + status_bit15_11[11] <= 1'b1 ; + else if (delete_status_bit11) // Synchronous reset + status_bit15_11[11] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit8 <= 1'b0 ; + else + begin + if (master_data_par_err) // Synchronous set + status_bit8 <= 1'b1 ; + else if (delete_status_bit8) // Synchronous reset + status_bit8 <= 1'b0 ; + end + end +`else // not SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + reg [15:11] set_status_bit15_11; + reg set_status_bit8; + wire delete_set_status_bit15; + wire delete_set_status_bit14; + wire delete_set_status_bit13; + wire delete_set_status_bit12; + wire delete_set_status_bit11; + wire delete_set_status_bit8; + wire block_set_status_bit15; + wire block_set_status_bit14; + wire block_set_status_bit13; + wire block_set_status_bit12; + wire block_set_status_bit11; + wire block_set_status_bit8; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_15 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit15), + .block_set_out (block_set_status_bit15), + .delete_in (delete_status_bit15) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit15_11[15] <= 1'b0 ; + else + begin + if (perr_in) // Synchronous set + set_status_bit15_11[15] <= 1'b1 ; + else if (delete_set_status_bit15) // Synchronous reset + set_status_bit15_11[15] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_14 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit14), + .block_set_out (block_set_status_bit14), + .delete_in (delete_status_bit14) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit15_11[14] <= 1'b0 ; + else + begin + if (serr_in) // Synchronous set + set_status_bit15_11[14] <= 1'b1 ; + else if (delete_set_status_bit14) // Synchronous reset + set_status_bit15_11[14] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_13 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit13), + .block_set_out (block_set_status_bit13), + .delete_in (delete_status_bit13) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit15_11[13] <= 1'b0 ; + else + begin + if (master_abort_recv) // Synchronous set + set_status_bit15_11[13] <= 1'b1 ; + else if (delete_set_status_bit13) // Synchronous reset + set_status_bit15_11[13] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_12 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit12), + .block_set_out (block_set_status_bit12), + .delete_in (delete_status_bit12) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit15_11[12] <= 1'b0 ; + else + begin + if (target_abort_recv) // Synchronous set + set_status_bit15_11[12] <= 1'b1 ; + else if (delete_set_status_bit12) // Synchronous reset + set_status_bit15_11[12] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_11 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit11), + .block_set_out (block_set_status_bit11), + .delete_in (delete_status_bit11) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit15_11[11] <= 1'b0 ; + else + begin + if (target_abort_set) // Synchronous set + set_status_bit15_11[11] <= 1'b1 ; + else if (delete_set_status_bit11) // Synchronous reset + set_status_bit15_11[11] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_status_8 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_status_bit8), + .block_set_out (block_set_status_bit8), + .delete_in (delete_status_bit8) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_status_bit8 <= 1'b0 ; + else + begin + if (master_data_par_err) // Synchronous set + set_status_bit8 <= 1'b1 ; + else if (delete_set_status_bit8) // Synchronous reset + set_status_bit8 <= 1'b0 ; + end + end + wire [5:0] status_bits = {set_status_bit15_11[15] && !block_set_status_bit15, + set_status_bit15_11[14] && !block_set_status_bit14, + set_status_bit15_11[13] && !block_set_status_bit13, + set_status_bit15_11[12] && !block_set_status_bit12, + set_status_bit15_11[11] && !block_set_status_bit11, + set_status_bit8 && !block_set_status_bit8 } ; + wire [5:0] meta_status_bits ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(6, 0) status_bits_sync + ( + .data_in (status_bits), + .clk_out (wb_clk), + .sync_data_out (meta_status_bits), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + begin + status_bit15_11[15:11] <= 5'b0 ; + status_bit8 <= 1'b0 ; + end + else + begin + status_bit15_11[15:11] <= meta_status_bits[5:1] ; + status_bit8 <= meta_status_bits[0] ; + end + end + `else // GUEST + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[15] <= 1'b0 ; + else + begin + if (perr_in) // Synchronous set + status_bit15_11[15] <= 1'b1 ; + else if (delete_status_bit15) // Synchronous reset + status_bit15_11[15] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[14] <= 1'b0 ; + else + begin + if (serr_in) // Synchronous set + status_bit15_11[14] <= 1'b1 ; + else if (delete_status_bit14) // Synchronous reset + status_bit15_11[14] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[13] <= 1'b0 ; + else + begin + if (master_abort_recv) // Synchronous set + status_bit15_11[13] <= 1'b1 ; + else if (delete_status_bit13) // Synchronous reset + status_bit15_11[13] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[12] <= 1'b0 ; + else + begin + if (target_abort_recv) // Synchronous set + status_bit15_11[12] <= 1'b1 ; + else if (delete_status_bit12) // Synchronous reset + status_bit15_11[12] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit15_11[11] <= 1'b0 ; + else + begin + if (target_abort_set) // Synchronous set + status_bit15_11[11] <= 1'b1 ; + else if (delete_status_bit11) // Synchronous reset + status_bit15_11[11] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + status_bit8 <= 1'b0 ; + else + begin + if (master_data_par_err) // Synchronous set + status_bit8 <= 1'b1 ; + else if (delete_status_bit8) // Synchronous reset + status_bit8 <= 1'b0 ; + end + end + `endif +`endif + +// STATUS BITS of P_ERR_CS - PCI error control and status register +`ifdef SYNCHRONEOUS_CLOCK_DOMAINS + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + pci_err_cs_bit8 <= 1'b0 ; + else + begin + if (pci_error_sig && pci_err_cs_bit0) // Synchronous set + pci_err_cs_bit8 <= 1'b1 ; + else if (delete_pci_err_cs_bit8) // Synchronous reset + pci_err_cs_bit8 <= 1'b0 ; + end + end +`else // not SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + // Set and clear FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + pci_err_cs_bit8 <= 1'b0 ; + else + begin + if (pci_error_sig && pci_err_cs_bit0) // Synchronous set + pci_err_cs_bit8 <= 1'b1 ; + else if (delete_pci_err_cs_bit8) // Synchronous reset + pci_err_cs_bit8 <= 1'b0 ; + end + end + `else // GUEST + reg set_pci_err_cs_bit8; + wire delete_set_pci_err_cs_bit8; + wire block_set_pci_err_cs_bit8; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_pci_err_cs_8 + ( + .set_clk_in (wb_clk), + .delete_clk_in (pci_clk), + .reset_in (reset), + .delete_set_out (delete_set_pci_err_cs_bit8), + .block_set_out (block_set_pci_err_cs_bit8), + .delete_in (delete_pci_err_cs_bit8) + ); + // Setting FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_pci_err_cs_bit8 <= 1'b0 ; + else + begin + if (pci_error_sig && pci_err_cs_bit0) // Synchronous set + set_pci_err_cs_bit8 <= 1'b1 ; + else if (delete_set_pci_err_cs_bit8) // Synchronous reset + set_pci_err_cs_bit8 <= 1'b0 ; + end + end + wire pci_err_cs_bits = set_pci_err_cs_bit8 && !block_set_pci_err_cs_bit8 ; + wire meta_pci_err_cs_bits ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1,0) pci_err_cs_bits_sync + ( + .data_in (pci_err_cs_bits), + .clk_out (pci_clk), + .sync_data_out (meta_pci_err_cs_bits), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + pci_err_cs_bit8 <= 1'b0 ; + else + pci_err_cs_bit8 <= meta_pci_err_cs_bits ; + end + `endif +`endif + // Set and clear FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + pci_err_cs_bit10 <= 1'b0 ; + else + begin + if (pci_error_sig) // Synchronous report + pci_err_cs_bit10 <= pci_error_rty_exp ; + end + end + // Set and clear FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + pci_err_cs_bit9 <= 1'b0 ; + else + begin + if (pci_error_sig) // Synchronous report + pci_err_cs_bit9 <= pci_error_es ; + end + end + // Set and clear FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + begin + pci_err_cs_bit31_24 <= 8'h00 ; + pci_err_addr <= 32'h0000_0000 ; + pci_err_data <= 32'h0000_0000 ; + end + else + if (pci_error_sig) // Synchronous report + begin + pci_err_cs_bit31_24 <= { pci_error_be, pci_error_bc } ; + pci_err_addr <= pci_error_addr ; + pci_err_data <= pci_error_data ; + end + end + +// STATUS BITS of W_ERR_CS - WB error control and status register +`ifdef SYNCHRONEOUS_CLOCK_DOMAINS + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + wb_err_cs_bit8 <= 1'b0 ; + else + begin + if (wb_error_sig && wb_err_cs_bit0) // Synchronous set + wb_err_cs_bit8 <= 1'b1 ; + else if (delete_wb_err_cs_bit8) // Synchronous reset + wb_err_cs_bit8 <= 1'b0 ; + end + end +`else // not SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + reg set_wb_err_cs_bit8; + wire delete_set_wb_err_cs_bit8; + wire block_set_wb_err_cs_bit8; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_wb_err_cs_8 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_wb_err_cs_bit8), + .block_set_out (block_set_wb_err_cs_bit8), + .delete_in (delete_wb_err_cs_bit8) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_wb_err_cs_bit8 <= 1'b0 ; + else + begin + if (wb_error_sig && wb_err_cs_bit0) // Synchronous set + set_wb_err_cs_bit8 <= 1'b1 ; + else if (delete_set_wb_err_cs_bit8) // Synchronous reset + set_wb_err_cs_bit8 <= 1'b0 ; + end + end + wire wb_err_cs_bits = set_wb_err_cs_bit8 && !block_set_wb_err_cs_bit8 ; + wire meta_wb_err_cs_bits ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1,0) wb_err_cs_bits_sync + ( + .data_in (wb_err_cs_bits), + .clk_out (wb_clk), + .sync_data_out (meta_wb_err_cs_bits), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + wb_err_cs_bit8 <= 1'b0 ; + else + wb_err_cs_bit8 <= meta_wb_err_cs_bits ; + end + `else // GUEST + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + wb_err_cs_bit8 <= 1'b0 ; + else + begin + if (wb_error_sig && wb_err_cs_bit0) // Synchronous set + wb_err_cs_bit8 <= 1'b1 ; + else if (delete_wb_err_cs_bit8) // Synchronous reset + wb_err_cs_bit8 <= 1'b0 ; + end + end + `endif +`endif +/* // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + wb_err_cs_bit10 <= 1'b0 ; + else + begin + if (wb_error_sig) // Synchronous report + wb_err_cs_bit10 <= wb_error_rty_exp ; + end + end */ + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + wb_err_cs_bit9 <= 1'b0 ; + else + begin + if (wb_error_sig) // Synchronous report + wb_err_cs_bit9 <= wb_error_es ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + begin + wb_err_cs_bit31_24 <= 8'h00 ; + wb_err_addr <= 32'h0000_0000 ; + wb_err_data <= 32'h0000_0000 ; + end + else + if (wb_error_sig) + begin + wb_err_cs_bit31_24 <= { wb_error_be, wb_error_bc } ; + wb_err_addr <= wb_error_addr ; + wb_err_data <= wb_error_data ; + end + end + +// SERR_INT and PERR_INT STATUS BITS of ISR - interrupt status register +`ifdef SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit4_3[4] <= 1'b0 ; + else + begin + if (isr_sys_err_int && icr_bit4_3[4]) // Synchronous set + isr_bit4_3[4] <= 1'b1 ; + else if (delete_isr_bit4) // Synchronous reset + isr_bit4_3[4] <= 1'b0 ; + end + end + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit4_3[3] <= 1'b0 ; + else + begin + if (isr_par_err_int && icr_bit4_3[3]) // Synchronous set + isr_bit4_3[3] <= 1'b1 ; + else if (delete_isr_bit3) // Synchronous reset + isr_bit4_3[3] <= 1'b0 ; + end + end + `endif +`else // not SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + reg [4:3] set_isr_bit4_3; + wire delete_set_isr_bit4; + wire delete_set_isr_bit3; + wire block_set_isr_bit4; + wire block_set_isr_bit3; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_isr_4 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_isr_bit4), + .block_set_out (block_set_isr_bit4), + .delete_in (delete_isr_bit4) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_isr_bit4_3[4] <= 1'b0 ; + else + begin + if (isr_sys_err_int && icr_bit4_3[4]) // Synchronous set + set_isr_bit4_3[4] <= 1'b1 ; + else if (delete_set_isr_bit4) // Synchronous reset + set_isr_bit4_3[4] <= 1'b0 ; + end + end + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_isr_3 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_isr_bit3), + .block_set_out (block_set_isr_bit3), + .delete_in (delete_isr_bit3) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_isr_bit4_3[3] <= 1'b0 ; + else + begin + if (isr_par_err_int && icr_bit4_3[3]) // Synchronous set + set_isr_bit4_3[3] <= 1'b1 ; + else if (delete_set_isr_bit3) // Synchronous reset + set_isr_bit4_3[3] <= 1'b0 ; + end + end + wire [4:3] isr_bits4_3 = {set_isr_bit4_3[4] && !block_set_isr_bit4, + set_isr_bit4_3[3] && !block_set_isr_bit3 } ; + wire [4:3] meta_isr_bits4_3 ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(2, 0) isr_bits_sync + ( + .data_in (isr_bits4_3), + .clk_out (wb_clk), + .sync_data_out (meta_isr_bits4_3), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + isr_bit4_3[4:3] <= 2'b0 ; + else + isr_bit4_3[4:3] <= meta_isr_bits4_3[4:3] ; + end + `endif +`endif + +// PCI_EINT and WB_EINT STATUS BITS of ISR - interrupt status register +`ifdef SYNCHRONEOUS_CLOCK_DOMAINS + // WB_EINT STATUS BIT + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit2_0[1] <= 1'b0 ; + else + begin + if (wb_error_sig && icr_bit2_0[1] && wb_err_cs_bit0) // Synchronous set + isr_bit2_0[1] <= 1'b1 ; + else if (delete_isr_bit1) // Synchronous reset + isr_bit2_0[1] <= 1'b0 ; + end + end + // PCI_EINT STATUS BIT + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit2_0[2] <= 1'b0 ; + else + begin + if (pci_error_sig && icr_bit2_0[2] && pci_err_cs_bit0) // Synchronous set + isr_bit2_0[2] <= 1'b1 ; + else if (delete_isr_bit2) // Synchronous reset + isr_bit2_0[2] <= 1'b0 ; + end + end +`else // not SYNCHRONEOUS_CLOCK_DOMAINS + `ifdef HOST + // WB_EINT STATUS BIT + reg set_isr_bit1; + wire delete_set_isr_bit1; + wire block_set_isr_bit1; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_isr_1 + ( + .set_clk_in (pci_clk), + .delete_clk_in (wb_clk), + .reset_in (reset), + .delete_set_out (delete_set_isr_bit1), + .block_set_out (block_set_isr_bit1), + .delete_in (delete_isr_bit1) + ); + // Setting FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_isr_bit1 <= 1'b0 ; + else + begin + if (wb_error_sig && icr_bit2_0[1] && wb_err_cs_bit0) // Synchronous set + set_isr_bit1 <= 1'b1 ; + else if (delete_set_isr_bit1) // Synchronous reset + set_isr_bit1 <= 1'b0 ; + end + end + wire isr_bit1 = set_isr_bit1 && !block_set_isr_bit1 ; + wire meta_isr_bit1 ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) isr_bit1_sync + ( + .data_in (isr_bit1), + .clk_out (wb_clk), + .sync_data_out (meta_isr_bit1), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + isr_bit2_0[1] <= 1'b0 ; + else + isr_bit2_0[1] <= meta_isr_bit1 ; + end + // PCI_EINT STATUS BIT + // Set and clear FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit2_0[2] <= 1'b0 ; + else + begin + if (pci_error_sig && icr_bit2_0[2] && pci_err_cs_bit0) // Synchronous set + isr_bit2_0[2] <= 1'b1 ; + else if (delete_isr_bit2) // Synchronous reset + isr_bit2_0[2] <= 1'b0 ; + end + end + `else // GUEST + // WB_EINT STATUS BIT + // Set and clear FF + always@(posedge pci_clk or posedge reset) + begin + if (reset) // Asynchronous reset + isr_bit2_0[1] <= 1'b0 ; + else + begin + if (wb_error_sig && icr_bit2_0[1] && wb_err_cs_bit0) // Synchronous set + isr_bit2_0[1] <= 1'b1 ; + else if (delete_isr_bit1) // Synchronous reset + isr_bit2_0[1] <= 1'b0 ; + end + end + // PCI_EINT STATUS BIT + reg set_isr_bit2; + wire delete_set_isr_bit2; + wire block_set_isr_bit2; + // Synchronization module for clearing FF between two clock domains + pci_sync_module sync_isr_2 + ( + .set_clk_in (wb_clk), + .delete_clk_in (pci_clk), + .reset_in (reset), + .delete_set_out (delete_set_isr_bit2), + .block_set_out (block_set_isr_bit2), + .delete_in (delete_isr_bit2) + ); + // Setting FF + always@(posedge wb_clk or posedge reset) + begin + if (reset) // Asynchronous reset + set_isr_bit2 <= 1'b0 ; + else + begin + if (pci_error_sig && icr_bit2_0[2] && pci_err_cs_bit0) // Synchronous set + set_isr_bit2 <= 1'b1 ; + else if (delete_set_isr_bit2) // Synchronous reset + set_isr_bit2 <= 1'b0 ; + end + end + wire isr_bit2 = set_isr_bit2 && !block_set_isr_bit2 ; + wire meta_isr_bit2 ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) isr_bit2_sync + ( + .data_in (isr_bit2), + .clk_out (pci_clk), + .sync_data_out (meta_isr_bit2), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + isr_bit2_0[2] <= 1'b0 ; + else + isr_bit2_0[2] <= meta_isr_bit2 ; + end + `endif +`endif + +// INT BIT of ISR - interrupt status register +`ifdef HOST + wire isr_int_prop_bit = isr_int_prop && icr_bit2_0[0] ; + wire meta_isr_int_prop_bit ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) isr_bit0_sync + ( + .data_in (isr_int_prop_bit), + .clk_out (wb_clk), + .sync_data_out (meta_isr_int_prop_bit), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + isr_bit2_0[0] <= 1'b0 ; + else + isr_bit2_0[0] <= meta_isr_int_prop_bit ; + end +`else // GUEST + `ifdef SYNCHRONEOUS_CLOCK_DOMAINS + wire isr_int_prop_bit = isr_int_prop && icr_bit2_0[0] ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + isr_bit2_0[0] <= 1'b0 ; + else + isr_bit2_0[0] <= isr_int_prop_bit ; + end + `else // not SYNCHRONEOUS_CLOCK_DOMAINS + wire isr_int_prop_bit = isr_int_prop && icr_bit2_0[0] ; + wire meta_isr_int_prop_bit ; + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) isr_bit0_sync + ( + .data_in (isr_int_prop_bit), + .clk_out (pci_clk), + .sync_data_out (meta_isr_int_prop_bit), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + isr_bit2_0[0] <= 1'b0 ; + else + isr_bit2_0[0] <= meta_isr_int_prop_bit ; + end + `endif +`endif + +// INT PIN +wire int_in; +wire int_meta; +reg interrupt_out; +`ifdef HOST + `ifdef SYNCHRONEOUS_CLOCK_DOMAINS + assign int_in = isr_int_prop_bit || isr_bit2_0[1] || isr_bit2_0[2] || isr_bit4_3[3] || isr_bit4_3[4]; + `else // not SYNCHRONEOUS_CLOCK_DOMAINS + assign int_in = isr_int_prop_bit || isr_bit1 || isr_bit2_0[2] || isr_bits4_3[3] || isr_bits4_3[4]; + `endif + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) int_pin_sync + ( + .data_in (int_in), + .clk_out (wb_clk), + .sync_data_out (int_meta), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + interrupt_out <= 1'b0 ; + else + interrupt_out <= int_meta ; + end +`else // GUEST + `ifdef SYNCHRONEOUS_CLOCK_DOMAINS + assign int_in = isr_int_prop_bit || isr_bit2_0[1] || isr_bit2_0[2]; + `else // not SYNCHRONEOUS_CLOCK_DOMAINS + assign int_in = isr_int_prop_bit || isr_bit2_0[1] || isr_bit2; + `endif + // interemediate stage to clk synchronization flip - flops - this ones are prone to metastability + pci_synchronizer_flop #(1, 0) int_pin_sync + ( + .data_in (int_in), + .clk_out (pci_clk), + .sync_data_out (int_meta), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + interrupt_out <= 1'b0 ; + else + interrupt_out <= int_meta ; + end +`endif + + +`ifdef PCI_CPCI_HS_IMPLEMENT + reg [hs_es_cnt_width - 1:0] hs_es_cnt ; // debounce counter + reg hs_es_in_state, // current state of ejector switch input - synchronized + hs_es_sync, // synchronization flop for ejector switch input + hs_es_cur_state ; // current valid state of ejector switch + +`ifdef ACTIVE_HIGH_OE + wire oe_active_val = 1'b1 ; +`endif + +`ifdef ACTIVE_LOW_OE + wire oe_active_val = 1'b0 ; +`endif + + always@(posedge pci_clk or posedge reset) + begin + if (reset) + begin + hs_ins <= 1'b0 ; + hs_ins_armed <= 1'b1 ; + hs_ext <= 1'b0 ; + hs_ext_armed <= 1'b0 ; + hs_es_in_state <= 1'b0 ; + hs_es_sync <= 1'b0 ; + hs_es_cur_state <= 1'b0 ; + hs_es_cnt <= 'h0 ; + + `ifdef ACTIVE_LOW_OE + pci_cpci_hs_enum_oe_o <= 1'b1 ; + pci_cpci_hs_led_oe_o <= 1'b0 ; + `endif + + `ifdef ACTIVE_HIGH_OE + pci_cpci_hs_enum_oe_o <= 1'b0 ; + pci_cpci_hs_led_oe_o <= 1'b1 ; + `endif + + end + else + begin + // INS + if (hs_ins) + begin + if (w_conf_data[23] & ~w_byte_en[2] & w_we & w_reg_select_dec[56]) // clear + hs_ins <= 1'b0 ; + end + else if (hs_ins_armed) // set + hs_ins <= init_complete & (hs_es_cur_state == 1'b1) ; + + // INS armed + if (~hs_ins & hs_ins_armed & init_complete & (hs_es_cur_state == 1'b1)) // clear + hs_ins_armed <= 1'b0 ; + else if (hs_ext) // set + hs_ins_armed <= w_conf_data[22] & ~w_byte_en[2] & w_we & w_reg_select_dec[56] ; + + // EXT + if (hs_ext) // clear + begin + if (w_conf_data[22] & ~w_byte_en[2] & w_we & w_reg_select_dec[56]) + hs_ext <= 1'b0 ; + end + else if (hs_ext_armed) // set + hs_ext <= (hs_es_cur_state == 1'b0) ; + + // EXT armed + if (~hs_ext & hs_ext_armed & (hs_es_cur_state == 1'b0)) // clear + hs_ext_armed <= 1'b0 ; + else if (hs_ins) // set + hs_ext_armed <= w_conf_data[23] & !w_byte_en[2] & w_we & w_reg_select_dec[56] ; + + // ejector switch debounce counter logic + hs_es_sync <= pci_cpci_hs_es_i ; + hs_es_in_state <= hs_es_sync ; + + if (hs_es_in_state == hs_es_cur_state) + hs_es_cnt <= 'h0 ; + else + hs_es_cnt <= hs_es_cnt + 1'b1 ; + + if (hs_es_cnt == {hs_es_cnt_width{1'b1}}) + hs_es_cur_state <= hs_es_in_state ; + + if ((hs_ins | hs_ext) & ~hs_eim) + pci_cpci_hs_enum_oe_o <= oe_active_val ; + else + pci_cpci_hs_enum_oe_o <= ~oe_active_val ; + + if (~init_complete | hs_loo) + pci_cpci_hs_led_oe_o <= oe_active_val ; + else + pci_cpci_hs_led_oe_o <= ~oe_active_val ; + end + end +`endif + +`ifdef PCI_SPOCI + + wire spoci_write_done, + spoci_dat_rdy , + spoci_no_ack ; + + wire [ 7: 0] spoci_wdat ; + wire [ 7: 0] spoci_rdat ; + + // power on configuration control and status register + always@(posedge pci_clk or posedge reset) + begin + if (reset) + begin + spoci_cs_nack <= 1'b0 ; + spoci_cs_write <= 1'b0 ; + spoci_cs_read <= 1'b0 ; + spoci_cs_adr <= 'h0 ; + spoci_cs_dat <= 'h0 ; + end + else + begin + if (spoci_cs_write) + begin + if (spoci_write_done | spoci_no_ack) + spoci_cs_write <= 1'b0 ; + end + else if ( w_we & (w_conf_address[9:2] == 8'hFF) & ~w_byte_en[3]) + spoci_cs_write <= w_conf_data[25] ; + + if (spoci_cs_read) + begin + if (spoci_dat_rdy | spoci_no_ack) + spoci_cs_read <= 1'b0 ; + end + else if ( w_we & (w_conf_address[9:2] == 8'hFF) & ~w_byte_en[3] ) + spoci_cs_read <= w_conf_data[24] ; + + if (spoci_cs_nack) + begin + if ( w_we & (w_conf_address[9:2] == 8'hFF) & ~w_byte_en[3] & w_conf_data[31] ) + spoci_cs_nack <= 1'b0 ; + end + else if (spoci_cs_write | spoci_cs_read | ~init_cfg_done) + begin + spoci_cs_nack <= spoci_no_ack ; + end + + if ( w_we & (w_conf_address[9:2] == 8'hFF) ) + begin + if (~w_byte_en[2]) + spoci_cs_adr[10: 8] <= w_conf_data[18:16] ; + + if (~w_byte_en[1]) + spoci_cs_adr[ 7: 0] <= w_conf_data[15: 8] ; + end + + if ( w_we & (w_conf_address[9:2] == 8'hFF) & ~w_byte_en[0] ) + spoci_cs_dat <= w_conf_data[ 7: 0] ; + else if (spoci_cs_read & spoci_dat_rdy) + spoci_cs_dat <= spoci_rdat ; + + end + end + + reg [ 2 : 0] bytes_received ; + + always@(posedge pci_clk or posedge reset) + begin + if (reset) + begin + init_we <= 1'b0 ; + init_cfg_done <= 1'b0 ; + bytes_received <= 1'b0 ; + spoci_dat <= 'h0 ; + spoci_reg_num <= 'h0 ; + end + else if (~init_cfg_done) + begin + if (spoci_dat_rdy) + begin + case (bytes_received) + 'h0:spoci_reg_num <= spoci_rdat ; + 'h1:spoci_dat[ 7: 0] <= spoci_rdat ; + 'h2:spoci_dat[15: 8] <= spoci_rdat ; + 'h3:spoci_dat[23:16] <= spoci_rdat ; + 'h4:spoci_dat[31:24] <= spoci_rdat ; + default: + begin + spoci_dat <= 32'hxxxx_xxxx ; + spoci_reg_num <= 'hxx ; + end + endcase + end + + if (init_we) + bytes_received <= 'h0 ; + else if (spoci_dat_rdy) + bytes_received <= bytes_received + 1'b1 ; + + if (init_we) + init_we <= 1'b0 ; + else if (bytes_received == 'h5) + init_we <= 1'b1 ; + + if (spoci_no_ack | ((bytes_received == 'h1) & (spoci_reg_num == 'hff)) ) + init_cfg_done <= 1'b1 ; + end + end + + assign spoci_wdat = spoci_cs_dat ; + + pci_spoci_ctrl i_pci_spoci_ctrl + ( + .reset_i (reset ), + .clk_i (pci_clk ), + + .do_rnd_read_i (spoci_cs_read ), + .do_seq_read_i (rst_inactive & ~init_cfg_done ), + .do_write_i (spoci_cs_write ), + + .write_done_o (spoci_write_done ), + .dat_rdy_o (spoci_dat_rdy ), + .no_ack_o (spoci_no_ack ), + + .adr_i (spoci_cs_adr ), + .dat_i (spoci_wdat ), + .dat_o (spoci_rdat ), + + .pci_spoci_sda_i (spoci_sda_i ), + .pci_spoci_sda_oe_o (spoci_sda_oe_o ), + .pci_spoci_scl_oe_o (spoci_scl_oe_o ) + ); +`endif + +/*----------------------------------------------------------------------------------------------------------- + OUTPUTs from registers !!! +-----------------------------------------------------------------------------------------------------------*/ + +// if bridge is HOST then write clock is equal to WB clock, and synchronization of outputs has to be done +`ifdef HOST + wire [3:0] command_bits = {command_bit8, command_bit6, command_bit2_0[1:0]} ; + wire [3:0] meta_command_bits ; + reg [3:0] sync_command_bits ; + pci_synchronizer_flop #(4, 0) command_bits_sync + ( + .data_in (command_bits), + .clk_out (pci_clk), + .sync_data_out (meta_command_bits), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + sync_command_bits <= 4'b0 ; + else + sync_command_bits <= meta_command_bits ; + end + wire sync_command_bit8 = sync_command_bits[3] ; + wire sync_command_bit6 = sync_command_bits[2] ; + wire sync_command_bit1 = sync_command_bits[1] ; + wire sync_command_bit0 = sync_command_bits[0] ; + wire sync_command_bit2 = command_bit2_0[2] ; +`else // GUEST + wire command_bit = command_bit2_0[2] ; + wire meta_command_bit ; + reg sync_command_bit ; + pci_synchronizer_flop #(1, 0) command_bit_sync + ( + .data_in (command_bit), + .clk_out (pci_clk), + .sync_data_out (meta_command_bit), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + sync_command_bit <= 1'b0 ; + else + sync_command_bit <= meta_command_bit ; + end + wire sync_command_bit8 = command_bit8 ; + wire sync_command_bit6 = command_bit6 ; + wire sync_command_bit1 = command_bit2_0[1] ; + wire sync_command_bit0 = command_bit2_0[0] ; + wire sync_command_bit2 = sync_command_bit ; +`endif +// PCI header outputs from command register +assign serr_enable = sync_command_bit8 & pci_init_complete_out ; // to PCI clock +assign perr_response = sync_command_bit6 & pci_init_complete_out ; // to PCI clock +assign pci_master_enable = sync_command_bit2 & wb_init_complete_out ; // to WB clock +assign memory_space_enable = sync_command_bit1 & pci_init_complete_out ; // to PCI clock +assign io_space_enable = sync_command_bit0 & pci_init_complete_out ; // to PCI clock + +// if bridge is HOST then write clock is equal to WB clock, and synchronization of outputs has to be done + // We don't support cache line sizes smaller that 4 and it must have last two bits zero!!! +wire cache_lsize_not_zero = ((cache_line_size_reg[7] || cache_line_size_reg[6] || cache_line_size_reg[5] || + cache_line_size_reg[4] || cache_line_size_reg[3] || cache_line_size_reg[2]) && + (!cache_line_size_reg[1] && !cache_line_size_reg[0]) ); +`ifdef HOST + wire [7:2] cache_lsize_to_pci_bits = { cache_line_size_reg[7:2] } ; + wire [7:2] meta_cache_lsize_to_pci_bits ; + reg [7:2] sync_cache_lsize_to_pci_bits ; + pci_synchronizer_flop #(6, 0) cache_lsize_to_pci_bits_sync + ( + .data_in (cache_lsize_to_pci_bits), + .clk_out (pci_clk), + .sync_data_out (meta_cache_lsize_to_pci_bits), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + sync_cache_lsize_to_pci_bits <= 6'b0 ; + else + sync_cache_lsize_to_pci_bits <= meta_cache_lsize_to_pci_bits ; + end + wire [7:2] sync_cache_line_size_to_pci_reg = sync_cache_lsize_to_pci_bits[7:2] ; + wire [7:2] sync_cache_line_size_to_wb_reg = cache_line_size_reg[7:2] ; + wire sync_cache_lsize_not_zero_to_wb = cache_lsize_not_zero ; +// Latency timer is sinchronized only to PCI clock when bridge implementation is HOST + wire [7:0] latency_timer_bits = latency_timer ; + wire [7:0] meta_latency_timer_bits ; + reg [7:0] sync_latency_timer_bits ; + pci_synchronizer_flop #(8, 0) latency_timer_bits_sync + ( + .data_in (latency_timer_bits), + .clk_out (pci_clk), + .sync_data_out (meta_latency_timer_bits), + .async_reset (reset) + ) ; + always@(posedge pci_clk or posedge reset) + begin + if (reset) + sync_latency_timer_bits <= 8'b0 ; + else + sync_latency_timer_bits <= meta_latency_timer_bits ; + end + wire [7:0] sync_latency_timer = sync_latency_timer_bits ; +`else // GUEST + wire [8:2] cache_lsize_to_wb_bits = { cache_lsize_not_zero, cache_line_size_reg[7:2] } ; + wire [8:2] meta_cache_lsize_to_wb_bits ; + reg [8:2] sync_cache_lsize_to_wb_bits ; + pci_synchronizer_flop #(7, 0) cache_lsize_to_wb_bits_sync + ( + .data_in (cache_lsize_to_wb_bits), + .clk_out (wb_clk), + .sync_data_out (meta_cache_lsize_to_wb_bits), + .async_reset (reset) + ) ; + always@(posedge wb_clk or posedge reset) + begin + if (reset) + sync_cache_lsize_to_wb_bits <= 7'b0 ; + else + sync_cache_lsize_to_wb_bits <= meta_cache_lsize_to_wb_bits ; + end + wire [7:2] sync_cache_line_size_to_pci_reg = cache_line_size_reg[7:2] ; + wire [7:2] sync_cache_line_size_to_wb_reg = sync_cache_lsize_to_wb_bits[7:2] ; + wire sync_cache_lsize_not_zero_to_wb = sync_cache_lsize_to_wb_bits[8] ; +// Latency timer + wire [7:0] sync_latency_timer = latency_timer ; +`endif +// PCI header output from cache_line_size, latency timer and interrupt pin +assign cache_line_size_to_pci = {sync_cache_line_size_to_pci_reg, 2'h0} ; // [7 : 0] to PCI clock +assign cache_line_size_to_wb = {sync_cache_line_size_to_wb_reg, 2'h0} ; // [7 : 0] to WB clock +assign cache_lsize_not_zero_to_wb = sync_cache_lsize_not_zero_to_wb ; + +assign latency_tim[7 : 0] = sync_latency_timer ; // to PCI clock +//assign int_pin[2 : 0] = r_interrupt_pin ; +assign int_out = interrupt_out ; +// PCI output from image registers +// base address, address mask, translation address and control registers are sinchronized in PCI_DECODER.V module +`ifdef HOST + `ifdef NO_CNF_IMAGE + assign pci_base_addr0 = pci_ba0_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; + `else + assign pci_base_addr0 = pci_ba0_bit31_8[31:12] ; + `endif +`endif + +`ifdef GUEST + assign pci_base_addr0 = pci_ba0_bit31_8[31:12] ; +`endif + +assign pci_base_addr1 = pci_ba1_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_base_addr2 = pci_ba2_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_base_addr3 = pci_ba3_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_base_addr4 = pci_ba4_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_base_addr5 = pci_ba5_bit31_8[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_memory_io0 = pci_ba0_bit0 ; +assign pci_memory_io1 = pci_ba1_bit0 ; +assign pci_memory_io2 = pci_ba2_bit0 ; +assign pci_memory_io3 = pci_ba3_bit0 ; +assign pci_memory_io4 = pci_ba4_bit0 ; +assign pci_memory_io5 = pci_ba5_bit0 ; + +assign pci_addr_mask0 = pci_am0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_addr_mask1 = pci_am1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_addr_mask2 = pci_am2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_addr_mask3 = pci_am3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_addr_mask4 = pci_am4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_addr_mask5 = pci_am5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr0 = pci_ta0[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr1 = pci_ta1[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr2 = pci_ta2[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr3 = pci_ta3[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr4 = pci_ta4[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_tran_addr5 = pci_ta5[31:(32-`PCI_NUM_OF_DEC_ADDR_LINES)] ; +assign pci_img_ctrl0[2 : 1] = pci_img_ctrl0_bit2_1 ; +assign pci_img_ctrl1[2 : 1] = pci_img_ctrl1_bit2_1 ; +assign pci_img_ctrl2[2 : 1] = pci_img_ctrl2_bit2_1 ; +assign pci_img_ctrl3[2 : 1] = pci_img_ctrl3_bit2_1 ; +assign pci_img_ctrl4[2 : 1] = pci_img_ctrl4_bit2_1 ; +assign pci_img_ctrl5[2 : 1] = pci_img_ctrl5_bit2_1 ; +// WISHBONE output from image registers +// base address, address mask, translation address and control registers are sinchronized in DECODER.V module +assign wb_base_addr0 = wb_ba0_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_base_addr1 = wb_ba1_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_base_addr2 = wb_ba2_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_base_addr3 = wb_ba3_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_base_addr4 = wb_ba4_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_base_addr5 = wb_ba5_bit31_12[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_memory_io0 = wb_ba0_bit0 ; +assign wb_memory_io1 = wb_ba1_bit0 ; +assign wb_memory_io2 = wb_ba2_bit0 ; +assign wb_memory_io3 = wb_ba3_bit0 ; +assign wb_memory_io4 = wb_ba4_bit0 ; +assign wb_memory_io5 = wb_ba5_bit0 ; +assign wb_addr_mask0 = wb_am0[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_addr_mask1 = wb_am1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_addr_mask2 = wb_am2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_addr_mask3 = wb_am3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_addr_mask4 = wb_am4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_addr_mask5 = wb_am5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr0 = wb_ta0[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr1 = wb_ta1[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr2 = wb_ta2[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr3 = wb_ta3[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr4 = wb_ta4[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_tran_addr5 = wb_ta5[31:(32-`WB_NUM_OF_DEC_ADDR_LINES)] ; +assign wb_img_ctrl0[2 : 0] = wb_img_ctrl0_bit2_0 ; +assign wb_img_ctrl1[2 : 0] = wb_img_ctrl1_bit2_0 ; +assign wb_img_ctrl2[2 : 0] = wb_img_ctrl2_bit2_0 ; +assign wb_img_ctrl3[2 : 0] = wb_img_ctrl3_bit2_0 ; +assign wb_img_ctrl4[2 : 0] = wb_img_ctrl4_bit2_0 ; +assign wb_img_ctrl5[2 : 0] = wb_img_ctrl5_bit2_0 ; +// GENERAL output from conf. cycle generation register & int. control register +assign config_addr[23 : 0] = { cnf_addr_bit23_2, 1'b0, cnf_addr_bit0 } ; +assign icr_soft_res = icr_bit31 ; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v new file mode 100644 index 000000000..c29391971 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v @@ -0,0 +1,170 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_constants.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// - Tadej Markovic (tadej@opencores.org) //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_constants.v,v $ +// Revision 1.2 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// + +// first include user definable parameters +`ifdef REGRESSION // Used only for regression testing purposes!!! + `include "pci_regression_constants.v" +`else + `include "pci_user_constants.v" +`endif + +//////////////////////////////////////////////////////////////////////// +//// //// +//// FIFO parameters define behaviour of FIFO control logic and //// +//// FIFO depths. //// +//// //// +//////////////////////////////////////////////////////////////////////// +`define WBW_DEPTH (1 << `WBW_ADDR_LENGTH) +`define WBR_DEPTH (1 << `WBR_ADDR_LENGTH) +`define PCIW_DEPTH (1 << `PCIW_ADDR_LENGTH) +`define PCIR_DEPTH (1 << `PCIR_ADDR_LENGTH) + +// defines on which bit in control bus means what +`define ADDR_CTRL_BIT 3 +`define LAST_CTRL_BIT 0 +`define DATA_ERROR_CTRL_BIT 1 +`define UNUSED_CTRL_BIT 2 +`define BURST_BIT 2 + +// MAX Retry counter value for PCI Master state-machine +// This value is 8-bit because of 8-bit retry counter !!! +//`define PCI_RTY_CNT_MAX 8'h08 + +// Value of address mask for WB configuration image. This has to be defined always, since it is a value, that is not changable in runtime. +// !!!!!!!!!!!!!!!!!!!!!!!If this is not defined, WB configuration access will not be possible!!!!!!!!!!!!!!!!!!!!!1 +`define WB_AM0 20'hffff_f + +// PCI target & WB slave ADDRESS names for configuration space !!! +// This does not include address offsets of PCI Header registers - they starts at offset 0 (see PCI spec.) +// ALL VALUES are without 2 LSBits AND there is required that address bit [8] is set while +// accessing this registers, otherwise the configuration header will be accessed !!! +`define PCI_CAP_PTR_VAL 8'h80 +`define P_IMG_CTRL0_ADDR 6'h00 // Address offset = h 100 +`define P_BA0_ADDR 6'h01 // Address offset = h 104 +`define P_AM0_ADDR 6'h02 // Address offset = h 108 +`define P_TA0_ADDR 6'h03 // Address offset = h 10c +`define P_IMG_CTRL1_ADDR 6'h04 // Address offset = h 110 +`define P_BA1_ADDR 6'h05 // Address offset = h 114 +`define P_AM1_ADDR 6'h06 // Address offset = h 118 +`define P_TA1_ADDR 6'h07 // Address offset = h 11c +`define P_IMG_CTRL2_ADDR 6'h08 // Address offset = h 120 +`define P_BA2_ADDR 6'h09 // Address offset = h 124 +`define P_AM2_ADDR 6'h0a // Address offset = h 128 +`define P_TA2_ADDR 6'h0b // Address offset = h 12c +`define P_IMG_CTRL3_ADDR 6'h0c // Address offset = h 130 +`define P_BA3_ADDR 6'h0d // Address offset = h 134 +`define P_AM3_ADDR 6'h0e // Address offset = h 138 +`define P_TA3_ADDR 6'h0f // Address offset = h 13c +`define P_IMG_CTRL4_ADDR 6'h10 // Address offset = h 140 +`define P_BA4_ADDR 6'h11 // Address offset = h 144 +`define P_AM4_ADDR 6'h12 // Address offset = h 148 +`define P_TA4_ADDR 6'h13 // Address offset = h 14c +`define P_IMG_CTRL5_ADDR 6'h14 // Address offset = h 150 +`define P_BA5_ADDR 6'h15 // Address offset = h 154 +`define P_AM5_ADDR 6'h16 // Address offset = h 158 +`define P_TA5_ADDR 6'h17 // Address offset = h 15c +`define P_ERR_CS_ADDR 6'h18 // Address offset = h 160 +`define P_ERR_ADDR_ADDR 6'h19 // Address offset = h 164 +`define P_ERR_DATA_ADDR 6'h1a // Address offset = h 168 + +`define WB_CONF_SPC_BAR_ADDR 6'h20 // Address offset = h 180 +`define W_IMG_CTRL1_ADDR 6'h21 // Address offset = h 184 +`define W_BA1_ADDR 6'h22 // Address offset = h 188 +`define W_AM1_ADDR 6'h23 // Address offset = h 18c +`define W_TA1_ADDR 6'h24 // Address offset = h 190 +`define W_IMG_CTRL2_ADDR 6'h25 // Address offset = h 194 +`define W_BA2_ADDR 6'h26 // Address offset = h 198 +`define W_AM2_ADDR 6'h27 // Address offset = h 19c +`define W_TA2_ADDR 6'h28 // Address offset = h 1a0 +`define W_IMG_CTRL3_ADDR 6'h29 // Address offset = h 1a4 +`define W_BA3_ADDR 6'h2a // Address offset = h 1a8 +`define W_AM3_ADDR 6'h2b // Address offset = h 1ac +`define W_TA3_ADDR 6'h2c // Address offset = h 1b0 +`define W_IMG_CTRL4_ADDR 6'h2d // Address offset = h 1b4 +`define W_BA4_ADDR 6'h2e // Address offset = h 1b8 +`define W_AM4_ADDR 6'h2f // Address offset = h 1bc +`define W_TA4_ADDR 6'h30 // Address offset = h 1c0 +`define W_IMG_CTRL5_ADDR 6'h31 // Address offset = h 1c4 +`define W_BA5_ADDR 6'h32 // Address offset = h 1c8 +`define W_AM5_ADDR 6'h33 // Address offset = h 1cc +`define W_TA5_ADDR 6'h34 // Address offset = h 1d0 +`define W_ERR_CS_ADDR 6'h35 // Address offset = h 1d4 +`define W_ERR_ADDR_ADDR 6'h36 // Address offset = h 1d8 +`define W_ERR_DATA_ADDR 6'h37 // Address offset = h 1dc +`define CNF_ADDR_ADDR 6'h38 // Address offset = h 1e0 +// Following two registers are not implemented in a configuration space but in a WishBone unit! +`define CNF_DATA_ADDR 6'h39 // Address offset = h 1e4 +`define INT_ACK_ADDR 6'h3a // Address offset = h 1e8 +// ------------------------------------- +`define ICR_ADDR 6'h3b // Address offset = h 1ec +`define ISR_ADDR 6'h3c // Address offset = h 1f0 + +`ifdef PCI33 + `define HEADER_66MHz 1'b0 +`else +`ifdef PCI66 + `define HEADER_66MHz 1'b1 +`endif +`endif + +// all flip-flops in the design have this inter-assignment delay +`define FF_DELAY 1 + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v new file mode 100644 index 000000000..ea8f287b9 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v @@ -0,0 +1,271 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "cur_out_reg.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_cur_out_reg.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" + +// module is only a backup copy of relevant output registers +// used in some arhitectures that support IOB registers, which have to have a +// fanout of 1 +// Otherwise nothing special in this module +module pci_cur_out_reg +( + reset_in, + clk_in, + frame_in, + frame_load_in, + irdy_in, + devsel_in, + trdy_in, + trdy_en_in, + stop_in, + ad_load_in, + cbe_in, + cbe_en_in, + mas_ad_in, + tar_ad_in, + frame_en_in, + irdy_en_in, + + mas_ad_en_in, + tar_ad_en_in, + ad_en_unregistered_in, + + par_in, + par_en_in, + perr_in, + perr_en_in, + serr_in, + serr_en_in, + + frame_out, + irdy_out, + devsel_out, + trdy_out, + stop_out, + cbe_out, + cbe_en_out, + ad_out, + frame_en_out, + irdy_en_out, + ad_en_out, + mas_ad_en_out, + tar_ad_en_out, + trdy_en_out, + + par_out, + par_en_out, + perr_out, + perr_en_out, + serr_out, + serr_en_out +) ; + +input reset_in, clk_in ; + +input frame_in ; +input frame_load_in ; +input irdy_in ; +input devsel_in ; +input trdy_in ; +input stop_in ; +input ad_load_in ; + +input [3:0] cbe_in ; +input cbe_en_in ; +input [31:0] mas_ad_in ; +input [31:0] tar_ad_in ; + +input mas_ad_en_in ; +input tar_ad_en_in ; +input ad_en_unregistered_in ; + +input frame_en_in, + irdy_en_in ; + +input trdy_en_in ; + +input par_in ; +input par_en_in ; +input perr_in ; +input perr_en_in ; +input serr_in ; +input serr_en_in ; + +output frame_out ; +reg frame_out ; +output irdy_out ; +reg irdy_out ; +output devsel_out ; +reg devsel_out ; +output trdy_out ; +reg trdy_out ; +output stop_out ; +reg stop_out ; +output [3:0] cbe_out ; +reg [3:0] cbe_out ; +output [31:0] ad_out ; +reg [31:0] ad_out ; + +output frame_en_out, + irdy_en_out, + ad_en_out, + cbe_en_out, + mas_ad_en_out, + tar_ad_en_out, + trdy_en_out ; + +reg frame_en_out, + irdy_en_out, + cbe_en_out, + mas_ad_en_out, + tar_ad_en_out, + trdy_en_out; + +output par_out ; +output par_en_out ; +output perr_out ; +output perr_en_out ; +output serr_out ; +output serr_en_out ; + +reg par_out ; +reg par_en_out ; +reg perr_out ; +reg perr_en_out ; +reg serr_out ; +reg serr_en_out ; + +assign ad_en_out = mas_ad_en_out || tar_ad_en_out ; + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + begin + irdy_out <= #`FF_DELAY 1'b1 ; + devsel_out <= #`FF_DELAY 1'b1 ; + trdy_out <= #`FF_DELAY 1'b1 ; + stop_out <= #`FF_DELAY 1'b1 ; + frame_en_out <= #`FF_DELAY 1'b0 ; + irdy_en_out <= #`FF_DELAY 1'b0 ; + mas_ad_en_out<= #`FF_DELAY 1'b0 ; + tar_ad_en_out<= #`FF_DELAY 1'b0 ; + trdy_en_out <= #`FF_DELAY 1'b0 ; + par_out <= #`FF_DELAY 1'b0 ; + par_en_out <= #`FF_DELAY 1'b0 ; + perr_out <= #`FF_DELAY 1'b1 ; + perr_en_out <= #`FF_DELAY 1'b0 ; + serr_out <= #`FF_DELAY 1'b1 ; + serr_en_out <= #`FF_DELAY 1'b0 ; + cbe_en_out <= #`FF_DELAY 1'b0 ; + + end + else + begin + irdy_out <= #`FF_DELAY irdy_in ; + devsel_out <= #`FF_DELAY devsel_in ; + trdy_out <= #`FF_DELAY trdy_in ; + stop_out <= #`FF_DELAY stop_in ; + frame_en_out <= #`FF_DELAY frame_en_in ; + irdy_en_out <= #`FF_DELAY irdy_en_in ; + mas_ad_en_out<= #`FF_DELAY mas_ad_en_in && ad_en_unregistered_in ; + tar_ad_en_out<= #`FF_DELAY tar_ad_en_in && ad_en_unregistered_in ; + trdy_en_out <= #`FF_DELAY trdy_en_in ; + + par_out <= #`FF_DELAY par_in ; + par_en_out <= #`FF_DELAY par_en_in ; + perr_out <= #`FF_DELAY perr_in ; + perr_en_out <= #`FF_DELAY perr_en_in ; + serr_out <= #`FF_DELAY serr_in ; + serr_en_out <= #`FF_DELAY serr_en_in ; + cbe_en_out <= #`FF_DELAY cbe_en_in ; + end +end + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + cbe_out <= #`FF_DELAY 4'hF ; + else if ( ad_load_in ) + cbe_out <= #`FF_DELAY cbe_in ; + +end + +wire [31:0] ad_source = tar_ad_en_out ? tar_ad_in : mas_ad_in ; + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + ad_out <= #`FF_DELAY 32'h0000_0000 ; + else if ( ad_load_in ) + ad_out <= #`FF_DELAY ad_source ; + +end + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + frame_out <= #`FF_DELAY 1'b1 ; + else if ( frame_load_in ) + frame_out <= #`FF_DELAY frame_in ; + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v new file mode 100644 index 000000000..b87244abb --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v @@ -0,0 +1,469 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "delayed_sync.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_delayed_sync.v,v $ +// Revision 1.3 2003/08/14 13:06:02 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// Revision 1.2 2003/03/26 13:16:18 mihad +// Added the reset value parameter to the synchronizer flop module. +// Added resets to all synchronizer flop instances. +// Repaired initial sync value in fifos. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.5 2002/09/25 09:54:50 mihad +// Added completion expiration test for WB Slave unit. Changed expiration signalling +// +// Revision 1.4 2002/03/05 11:53:47 mihad +// Added some testcases, removed un-needed fifo signals +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module provides synchronization mechanism between requesting and completing side of the bridge +`include "pci_constants.v" +`include "bus_commands.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_delayed_sync +( + reset_in, + req_clk_in, + comp_clk_in, + req_in, + comp_in, + done_in, + in_progress_in, + comp_req_pending_out, + req_req_pending_out, + req_comp_pending_out, + comp_comp_pending_out, + addr_in, + be_in, + addr_out, + be_out, + we_in, + we_out, + bc_in, + bc_out, + status_in, + status_out, + comp_flush_out, + burst_in, + burst_out, + retry_expired_in +); + +// system inputs +input reset_in, // reset input + req_clk_in, // requesting clock input + comp_clk_in ; // completing clock input + +// request, completion, done and in progress indication inputs +input req_in, // request qualifier - when 1 it indicates that valid request data is provided on inputs + comp_in, // completion qualifier - when 1, completing side indicates that request has completed + done_in, // done input - when 1 indicates that requesting side of the bridge has completed a transaction on requesting bus + in_progress_in ; // in progress indicator - indicates that current completion is in progress on requesting side of the bridge + +// pending indication outputs +output comp_req_pending_out, // completion side request output - resynchronized from requesting clock to completing clock + req_req_pending_out, // request pending output for requesting side + req_comp_pending_out, // completion pending output for requesting side of the bridge - it indicates when completion is ready for completing on requesting bus + comp_comp_pending_out ; // completion pending output for completing side of the bridge + +// additional signals and wires for clock domain passage of signals +reg comp_req_pending, + req_req_pending, + req_comp_pending, + req_comp_pending_sample, + comp_comp_pending, + req_done_reg, + comp_done_reg_main, + comp_done_reg_clr, + req_rty_exp_reg, + req_rty_exp_clr, + comp_rty_exp_reg, + comp_rty_exp_clr ; + +wire sync_comp_req_pending, + sync_req_comp_pending, + sync_comp_done, + sync_req_rty_exp, + sync_comp_rty_exp_clr ; + +// inputs from requesting side - only this side can set address, bus command, byte enables, write enable and burst - outputs are common for both sides +// all signals that identify requests are stored in this module + +input [31:0] addr_in ; // address bus input +input [3:0] be_in ; // byte enable input +input we_in ; // write enable input - read/write request indication 1 = write request / 0 = read request +input [3:0] bc_in ; // bus command input +input burst_in ; // burst indicator - qualifies operation as burst/single transfer 1 = burst / 0 = single transfer + +// common request outputs used both by completing and requesting sides +// this outputs are not resynchronized, since flags determine the request status +output [31:0] addr_out ; +output [3:0] be_out ; +output we_out ; +output [3:0] bc_out ; +output burst_out ; + +// completion side signals encoded termination status - 0 = normal completion / 1 = error terminated completion +input status_in ; +output status_out ; + +// input signals that delayed transaction has been retried for max number of times +// on this signal request is ditched, otherwise it would cause a deadlock +// requestor can issue another request and procedure will be repeated +input retry_expired_in ; + +// completion flush output - if in 2^^16 clock cycles transaction is not repeated by requesting agent - flush completion data +output comp_flush_out ; + +// output registers for common signals +reg [31:0] addr_out ; +reg [3:0] be_out ; +reg we_out ; +reg [3:0] bc_out ; +reg burst_out ; + +// delayed transaction information is stored only when request is issued and request nor completion are pending +wire new_request = req_in && ~req_comp_pending_out && ~req_req_pending_out ; +always@(posedge req_clk_in or posedge reset_in) +begin + if (reset_in) + begin + addr_out <= #`FF_DELAY 32'h0000_0000 ; + be_out <= #`FF_DELAY 4'h0 ; + we_out <= #`FF_DELAY 1'b0 ; + bc_out <= #`FF_DELAY `BC_RESERVED0 ; + burst_out <= #`FF_DELAY 1'b0 ; + end + else + if (new_request) + begin + addr_out <= #`FF_DELAY addr_in ; + be_out <= #`FF_DELAY be_in ; + we_out <= #`FF_DELAY we_in ; + bc_out <= #`FF_DELAY bc_in ; + burst_out <= #`FF_DELAY burst_in ; + end +end + +// completion pending cycle counter +reg [16:0] comp_cycle_count ; + +/*================================================================================================================================= +Passing of requests between clock domains: +request originates on requesting side. It's then synchronized with two flip-flops to cross to completing clock domain +=================================================================================================================================*/ +// main request flip-flop triggered on requesting side's clock +// request is cleared whenever completion or retry expired is signalled from opposite side of the bridge +wire req_req_clear = req_comp_pending || (req_rty_exp_reg && ~req_rty_exp_clr) ; +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_req_pending <= #`FF_DELAY 1'b0 ; + else + if ( req_req_clear ) + req_req_pending <= #`FF_DELAY 1'b0 ; + else + if ( req_in ) + req_req_pending <= #`FF_DELAY 1'b1 ; +end + +// interemediate stage request synchronization flip - flop - this one is prone to metastability +// and should have setup and hold times disabled during simulation +pci_synchronizer_flop #(1, 0) req_sync +( + .data_in (req_req_pending), + .clk_out (comp_clk_in), + .sync_data_out (sync_comp_req_pending), + .async_reset (reset_in) +) ; + +// wire for clearing completion side request flag - whenever completion or retry expired are signalled +wire comp_req_pending_clear = comp_req_pending && ( comp_in || retry_expired_in) ; + +// wire for enabling request flip - flop - it is enabled when completion is not active and done is not active +wire comp_req_pending_ena = ~comp_comp_pending && ~comp_done_reg_main && ~comp_rty_exp_reg ; + +// completion side request flip flop - gets a value from intermediate stage sync flip flop +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_req_pending <= #`FF_DELAY 1'b0 ; + else + if ( comp_req_pending_clear ) + comp_req_pending <= #`FF_DELAY 1'b0 ; + else + if ( comp_req_pending_ena ) + comp_req_pending <= #`FF_DELAY sync_comp_req_pending ; +end + +// completion side request output assignment - when request ff is set and completion ff is not set +assign comp_req_pending_out = comp_req_pending ; + +// requesting side request pending output +assign req_req_pending_out = req_req_pending ; +/*================================================================================================================================= +Passing of completions between clock domains: +completion originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain +=================================================================================================================================*/ +// main completion Flip - Flop - triggered by completing side's clock +// completion side completion pending flag is cleared when done flag propagates through clock domains +wire comp_comp_clear = comp_done_reg_main && ~comp_done_reg_clr ; +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_comp_pending <= #`FF_DELAY 1'b0 ; + else + if ( comp_comp_clear ) + comp_comp_pending <= #`FF_DELAY 1'b0 ; + else + if ( comp_in && comp_req_pending ) + comp_comp_pending <= #`FF_DELAY 1'b1 ; +end + +assign comp_comp_pending_out = comp_comp_pending ; + +// interemediate stage completion synchronization flip - flop - this one is prone to metastability +pci_synchronizer_flop #(1, 0) comp_sync +( + .data_in (comp_comp_pending), + .clk_out (req_clk_in), + .sync_data_out (sync_req_comp_pending), + .async_reset (reset_in) +) ; + +// request side completion pending flip flop is cleared whenever done is signalled or completion counter expires - 2^^16 clock cycles +wire req_comp_pending_clear = done_in || comp_cycle_count[16]; + +// request side completion pending flip flop is disabled while done flag is set +wire req_comp_pending_ena = ~req_done_reg ; + +// request side completion flip flop - gets a value from intermediate stage sync flip flop +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_comp_pending <= #`FF_DELAY 1'b0 ; + else + if ( req_comp_pending_clear ) + req_comp_pending <= #`FF_DELAY 1'b0 ; + else + if ( req_comp_pending_ena ) + req_comp_pending <= #`FF_DELAY sync_req_comp_pending ; +end + +// sampling FF - used for sampling incoming completion flag from completing side +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_comp_pending_sample <= #`FF_DELAY 1'b0 ; + else + req_comp_pending_sample <= #`FF_DELAY sync_req_comp_pending ; +end + +// requesting side completion pending output assignment +assign req_comp_pending_out = req_comp_pending && ~req_req_pending ; + +/*================================================================================================================================== +Passing of delayed transaction done signal between clock domains. +Done is signalled by requesting side of the bridge and is passed to completing side of the bridge +==================================================================================================================================*/ +// main done flip-flop triggered on requesting side's clock +// when completing side removes completion flag, done flag is also removed, so requests can proceede +wire req_done_clear = ~req_comp_pending_sample ; +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_done_reg <= #`FF_DELAY 1'b0 ; + else + if ( req_done_clear ) + req_done_reg <= #`FF_DELAY 1'b0 ; + else + if ( done_in || comp_cycle_count[16] ) + req_done_reg <= #`FF_DELAY 1'b1 ; +end + +pci_synchronizer_flop #(1, 0) done_sync +( + .data_in (req_done_reg), + .clk_out (comp_clk_in), + .sync_data_out (sync_comp_done), + .async_reset (reset_in) +) ; + +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_done_reg_main <= #`FF_DELAY 1'b0 ; + else + comp_done_reg_main <= #`FF_DELAY sync_comp_done ; +end + +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_done_reg_clr <= #`FF_DELAY 1'b0 ; + else + comp_done_reg_clr <= #`FF_DELAY comp_done_reg_main ; +end + +/*================================================================================================================================= +Passing of retry expired signal between clock domains +Retry expiration originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain +=================================================================================================================================*/ +// main retry expired Flip - Flop - triggered by completing side's clock +wire comp_rty_exp_clear = comp_rty_exp_clr && comp_rty_exp_reg ; + +// retry expired is a special case of transaction removal - retry expired propagates from completing +// clock domain to requesting clock domain to remove all pending requests and than propagates back +// to completing side to qualify valid new requests + +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_rty_exp_reg <= #`FF_DELAY 1'b0 ; + else + if ( comp_rty_exp_clear ) + comp_rty_exp_reg <= #`FF_DELAY 1'b0 ; + else + if ( retry_expired_in && comp_req_pending) + comp_rty_exp_reg <= #`FF_DELAY 1'b1 ; +end + +// interemediate stage retry expired synchronization flip - flop - this one is prone to metastability +pci_synchronizer_flop #(1, 0) rty_exp_sync +( + .data_in (comp_rty_exp_reg), + .clk_out (req_clk_in), + .sync_data_out (sync_req_rty_exp), + .async_reset (reset_in) +) ; + +// request retry expired flip flop - gets a value from intermediate stage sync flip flop +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_rty_exp_reg <= #`FF_DELAY 1'b0 ; + else + req_rty_exp_reg <= #`FF_DELAY sync_req_rty_exp ; +end + +always@(posedge req_clk_in or posedge reset_in) +begin + if ( reset_in ) + req_rty_exp_clr <= #`FF_DELAY 1'b0 ; + else + req_rty_exp_clr <= #`FF_DELAY req_rty_exp_reg ; +end + +pci_synchronizer_flop #(1, 0) rty_exp_back_prop_sync +( + .data_in (req_rty_exp_reg && req_rty_exp_clr), + .clk_out (comp_clk_in), + .sync_data_out (sync_comp_rty_exp_clr), + .async_reset (reset_in) +) ; + +always@(posedge comp_clk_in or posedge reset_in) +begin + if ( reset_in ) + comp_rty_exp_clr <= #`FF_DELAY 1'b0 ; + else + comp_rty_exp_clr <= #`FF_DELAY sync_comp_rty_exp_clr ; +end + +// completion status flip flop - if 0 when completion is signalled it's finished OK otherwise it means error +reg status_out ; +always@(posedge comp_clk_in or posedge reset_in) +begin + if (reset_in) + status_out <= #`FF_DELAY 1'b0 ; + else + if (comp_in && comp_req_pending) + status_out <= #`FF_DELAY status_in ; +end + +// clocks counter - it counts how many clock cycles completion is present without beeing repeated +// if it counts to 2^^16 cycles the completion must be ditched + +// wire for clearing this counter +wire clear_count = in_progress_in || ~req_comp_pending_out || comp_cycle_count[16] ; +always@(posedge req_clk_in or posedge reset_in) +begin + if (reset_in) + comp_cycle_count <= #`FF_DELAY 17'h0_0000 ; + else + if (clear_count) + comp_cycle_count <= #`FF_DELAY 17'h0_0000 ; + else + comp_cycle_count <= #`FF_DELAY comp_cycle_count + 1'b1 ; +end + +// completion flush output - used for flushing fifos when counter expires +// if counter doesn't expire, fifo flush is up to WISHBONE slave or PCI target state machines +reg comp_flush_out ; +always@(posedge req_clk_in or posedge reset_in) +begin + if (reset_in) + comp_flush_out <= #`FF_DELAY 1'b0 ; + else + comp_flush_out <= #`FF_DELAY comp_cycle_count[16] ; +end + +endmodule //delayed_sync diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v new file mode 100644 index 000000000..42f871ad5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v @@ -0,0 +1,95 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "delayed_write_reg.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_delayed_write_reg.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_delayed_write_reg +( + reset_in, + req_clk_in, + comp_wdata_out, + req_we_in, + req_wdata_in +); + +// system inputs +input reset_in, + req_clk_in ; // request clock input + +output [31:0] comp_wdata_out ; // data output + +input req_we_in ; // write enable input +input [31:0] req_wdata_in ; // data input - latched with posedge of req_clk_in when req_we_in is high + +reg [31:0] comp_wdata_out ; + +// write request operation +always@(posedge req_clk_in or posedge reset_in) +begin + if (reset_in) + comp_wdata_out <= #`FF_DELAY 32'h0000_0000 ; + else + if (req_we_in) + comp_wdata_out <= #`FF_DELAY req_wdata_in ; +end + +endmodule // DELAYED_WRITE_REG diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v new file mode 100644 index 000000000..6de6fa586 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v @@ -0,0 +1,83 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "frame_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_frame_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// this one is used in master state machine for driving correct value of frame output + +module pci_frame_crit +( + pci_frame_out, + force_frame_in, + slow_frame_in, + pci_stop_in +) ; + +output pci_frame_out ; +input force_frame_in, + slow_frame_in, + pci_stop_in ; + +assign pci_frame_out = force_frame_in && (slow_frame_in || ~pci_stop_in) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v new file mode 100644 index 000000000..2dcfffc02 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "frame_en_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_frame_en_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// This one is used in master state machine for frame output enable driving + +module pci_frame_en_crit +( + pci_frame_en_out, + frame_en_slow_in, + frame_en_keep_in, + pci_stop_in, + pci_trdy_in +) ; + +output pci_frame_en_out ; +input frame_en_slow_in, + frame_en_keep_in, + pci_stop_in, + pci_trdy_in ; + +assign pci_frame_en_out = frame_en_slow_in || frame_en_keep_in && pci_stop_in && pci_trdy_in ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v new file mode 100644 index 000000000..2ad22ae32 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "frame_load_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_frame_load_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// This one is used in master state machine for frame output flip flop clock enable driving +module pci_frame_load_crit +( + pci_frame_load_out, + sm_data_phases_in, + frame_load_slow_in, + pci_trdy_in, + pci_stop_in +) ; + +output pci_frame_load_out ; +input sm_data_phases_in, + frame_load_slow_in, + pci_trdy_in, + pci_stop_in ; + +assign pci_frame_load_out = frame_load_slow_in || sm_data_phases_in && (~(pci_trdy_in && pci_stop_in)) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v new file mode 100644 index 000000000..53a2c79fd --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v @@ -0,0 +1,160 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_in_reg.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_in_reg.v,v $ +// Revision 1.5 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:29 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" +// Module is used for registering PCI input signals +// It provides data flip flops with reset +module pci_in_reg +( + reset_in, + clk_in, + init_complete_in, + + pci_gnt_in, + pci_frame_in, + pci_irdy_in, + pci_trdy_in, + pci_stop_in, + pci_devsel_in, + pci_idsel_in, + pci_ad_in, + pci_cbe_in, + + pci_gnt_reg_out, + pci_frame_reg_out, + pci_irdy_reg_out, + pci_trdy_reg_out, + pci_stop_reg_out, + pci_devsel_reg_out, + pci_idsel_reg_out, + pci_ad_reg_out, + pci_cbe_reg_out + +); + +input reset_in, clk_in, init_complete_in ; + +input pci_gnt_in ; +input pci_frame_in ; +input pci_irdy_in ; +input pci_trdy_in ; +input pci_stop_in ; +input pci_devsel_in ; +input pci_idsel_in ; +input [31:0] pci_ad_in ; +input [3:0] pci_cbe_in ; + +output pci_gnt_reg_out ; +output pci_frame_reg_out ; +output pci_irdy_reg_out ; +output pci_trdy_reg_out ; +output pci_stop_reg_out ; +output pci_devsel_reg_out ; +output pci_idsel_reg_out ; +output [31:0] pci_ad_reg_out ; +output [3:0] pci_cbe_reg_out ; + + +reg pci_gnt_reg_out ; +reg pci_frame_reg_out ; +reg pci_irdy_reg_out ; +reg pci_trdy_reg_out ; +reg pci_stop_reg_out ; +reg pci_devsel_reg_out ; +reg pci_idsel_reg_out ; +reg [31:0] pci_ad_reg_out ; +reg [3:0] pci_cbe_reg_out ; + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + begin + pci_gnt_reg_out <= #`FF_DELAY 1'b1 ; + pci_frame_reg_out <= #`FF_DELAY 1'b0 ; + pci_irdy_reg_out <= #`FF_DELAY 1'b1 ; + pci_trdy_reg_out <= #`FF_DELAY 1'b1 ; + pci_stop_reg_out <= #`FF_DELAY 1'b1 ; + pci_devsel_reg_out <= #`FF_DELAY 1'b1 ; + pci_idsel_reg_out <= #`FF_DELAY 1'b0 ; // active high! + pci_ad_reg_out <= #`FF_DELAY 32'h0000_0000 ; + pci_cbe_reg_out <= #`FF_DELAY 4'h0 ; + end + else if (init_complete_in) + begin + pci_gnt_reg_out <= #`FF_DELAY pci_gnt_in ; + pci_frame_reg_out <= #`FF_DELAY pci_frame_in ; + pci_irdy_reg_out <= #`FF_DELAY pci_irdy_in ; + pci_trdy_reg_out <= #`FF_DELAY pci_trdy_in ; + pci_stop_reg_out <= #`FF_DELAY pci_stop_in ; + pci_devsel_reg_out <= #`FF_DELAY pci_devsel_in ; + pci_idsel_reg_out <= #`FF_DELAY pci_idsel_in ; + pci_ad_reg_out <= #`FF_DELAY pci_ad_in ; + pci_cbe_reg_out <= #`FF_DELAY pci_cbe_in ; + end +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v new file mode 100644 index 000000000..f0882dfe8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v @@ -0,0 +1,855 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_io_mux.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_io_mux.v,v $ +// Revision 1.5 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:29 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// this module instantiates output flip flops for PCI interface and +// some fanout downsizing logic because of heavily constrained PCI signals + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_io_mux +( + reset_in, + clk_in, + frame_in, + frame_en_in, + frame_load_in, + irdy_in, + irdy_en_in, + devsel_in, + devsel_en_in, + trdy_in, + trdy_en_in, + stop_in, + stop_en_in, + master_load_in, + master_load_on_transfer_in, + target_load_in, + target_load_on_transfer_in, + cbe_in, + cbe_en_in, + mas_ad_in, + tar_ad_in, + + par_in, + par_en_in, + perr_in, + perr_en_in, + serr_in, + serr_en_in, + + req_in, + + mas_ad_en_in, + tar_ad_en_in, + tar_ad_en_reg_in, + + ad_en_out, + frame_en_out, + irdy_en_out, + devsel_en_out, + trdy_en_out, + stop_en_out, + cbe_en_out, + + frame_out, + irdy_out, + devsel_out, + trdy_out, + stop_out, + cbe_out, + ad_out, + ad_load_out, + ad_en_unregistered_out, + + par_out, + par_en_out, + perr_out, + perr_en_out, + serr_out, + serr_en_out, + + req_out, + req_en_out, + pci_trdy_in, + pci_irdy_in, + pci_frame_in, + pci_stop_in, + + init_complete_in +); + +input reset_in, clk_in ; + +input frame_in ; +input frame_en_in ; +input frame_load_in ; +input irdy_in ; +input irdy_en_in ; +input devsel_in ; +input devsel_en_in ; +input trdy_in ; +input trdy_en_in ; +input stop_in ; +input stop_en_in ; +input master_load_in ; +input target_load_in ; + +input [3:0] cbe_in ; +input cbe_en_in ; +input [31:0] mas_ad_in ; +input [31:0] tar_ad_in ; + +input mas_ad_en_in ; +input tar_ad_en_in ; +input tar_ad_en_reg_in ; + +input par_in ; +input par_en_in ; +input perr_in ; +input perr_en_in ; +input serr_in ; +input serr_en_in ; + +output frame_en_out ; +output irdy_en_out ; +output devsel_en_out ; +output trdy_en_out ; +output stop_en_out ; +output [31:0] ad_en_out ; +output [3:0] cbe_en_out ; + +output frame_out ; +output irdy_out ; +output devsel_out ; +output trdy_out ; +output stop_out ; +output [3:0] cbe_out ; +output [31:0] ad_out ; +output ad_load_out ; +output ad_en_unregistered_out ; + +output par_out ; +output par_en_out ; +output perr_out ; +output perr_en_out ; +output serr_out ; +output serr_en_out ; + +input req_in ; + +output req_out ; +output req_en_out ; + +input pci_trdy_in, + pci_irdy_in, + pci_frame_in, + pci_stop_in ; + +input master_load_on_transfer_in ; +input target_load_on_transfer_in ; + +input init_complete_in ; + +wire [31:0] temp_ad = tar_ad_en_reg_in ? tar_ad_in : mas_ad_in ; + +wire ad_en_ctrl_low ; + +wire ad_en_ctrl_mlow ; + +wire ad_en_ctrl_mhigh ; + +wire ad_en_ctrl_high ; + +wire ad_enable_internal = mas_ad_en_in || tar_ad_en_in ; + +pci_io_mux_ad_en_crit ad_en_low_gen +( + .ad_en_in (ad_enable_internal), + .pci_frame_in (pci_frame_in), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in), + .ad_en_out (ad_en_ctrl_low) +); + +pci_io_mux_ad_en_crit ad_en_mlow_gen +( + .ad_en_in (ad_enable_internal), + .pci_frame_in (pci_frame_in), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in), + .ad_en_out (ad_en_ctrl_mlow) +); + +pci_io_mux_ad_en_crit ad_en_mhigh_gen +( + .ad_en_in (ad_enable_internal), + .pci_frame_in (pci_frame_in), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in), + .ad_en_out (ad_en_ctrl_mhigh) +); + +pci_io_mux_ad_en_crit ad_en_high_gen +( + .ad_en_in (ad_enable_internal), + .pci_frame_in (pci_frame_in), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in), + .ad_en_out (ad_en_ctrl_high) +); + +assign ad_en_unregistered_out = ad_en_ctrl_high ; + +wire load = master_load_in || target_load_in ; +wire load_on_transfer = master_load_on_transfer_in || target_load_on_transfer_in ; + +wire ad_load_ctrl_low ; +wire ad_load_ctrl_mlow ; +wire ad_load_ctrl_mhigh ; +wire ad_load_ctrl_high ; + +assign ad_load_out = ad_load_ctrl_high ; + +pci_io_mux_ad_load_crit ad_load_low_gen +( + .load_in(load), + .load_on_transfer_in(load_on_transfer), + .pci_irdy_in(pci_irdy_in), + .pci_trdy_in(pci_trdy_in), + .load_out(ad_load_ctrl_low) +); + +pci_io_mux_ad_load_crit ad_load_mlow_gen +( + .load_in(load), + .load_on_transfer_in(load_on_transfer), + .pci_irdy_in(pci_irdy_in), + .pci_trdy_in(pci_trdy_in), + .load_out(ad_load_ctrl_mlow) +); + +pci_io_mux_ad_load_crit ad_load_mhigh_gen +( + .load_in(load), + .load_on_transfer_in(load_on_transfer), + .pci_irdy_in(pci_irdy_in), + .pci_trdy_in(pci_trdy_in), + .load_out(ad_load_ctrl_mhigh) +); + +pci_io_mux_ad_load_crit ad_load_high_gen +( + .load_in(load), + .load_on_transfer_in(load_on_transfer), + .pci_irdy_in(pci_irdy_in), + .pci_trdy_in(pci_trdy_in), + .load_out(ad_load_ctrl_high) +); + +pci_out_reg ad_iob0 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[0] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[0] ), + .dat_out ( ad_out[0] ) +); + +pci_out_reg ad_iob1 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[1] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[1] ), + .dat_out ( ad_out[1] ) +); + +pci_out_reg ad_iob2 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[2] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[2] ), + .dat_out ( ad_out[2] ) +); + +pci_out_reg ad_iob3 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[3] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[3] ), + .dat_out ( ad_out[3] ) +); + +pci_out_reg ad_iob4 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[4] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[4] ), + .dat_out ( ad_out[4] ) +); + +pci_out_reg ad_iob5 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[5] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[5] ), + .dat_out ( ad_out[5] ) +); + +pci_out_reg ad_iob6 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[6] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[6] ), + .dat_out ( ad_out[6] ) +); + +pci_out_reg ad_iob7 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_low ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[7] ) , + .en_in ( ad_en_ctrl_low ) , + .en_out ( ad_en_out[7] ), + .dat_out ( ad_out[7] ) +); + +pci_out_reg ad_iob8 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[8] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[8] ), + .dat_out ( ad_out[8] ) +); + +pci_out_reg ad_iob9 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[9] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[9] ), + .dat_out ( ad_out[9] ) +); + +pci_out_reg ad_iob10 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[10] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[10] ), + .dat_out ( ad_out[10] ) +); + +pci_out_reg ad_iob11 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[11] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[11] ), + .dat_out ( ad_out[11] ) +); + +pci_out_reg ad_iob12 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[12] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[12] ), + .dat_out ( ad_out[12] ) +); + +pci_out_reg ad_iob13 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[13] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[13] ), + .dat_out ( ad_out[13] ) +); + +pci_out_reg ad_iob14 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[14] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[14] ), + .dat_out ( ad_out[14] ) +); + +pci_out_reg ad_iob15 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mlow ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[15] ) , + .en_in ( ad_en_ctrl_mlow ) , + .en_out ( ad_en_out[15] ), + .dat_out ( ad_out[15] ) +); + +pci_out_reg ad_iob16 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[16] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[16] ), + .dat_out ( ad_out[16] ) +); + +pci_out_reg ad_iob17 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[17] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[17] ), + .dat_out ( ad_out[17] ) +); + +pci_out_reg ad_iob18 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[18] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[18] ), + .dat_out ( ad_out[18] ) +); + +pci_out_reg ad_iob19 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[19] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[19] ), + .dat_out ( ad_out[19] ) +); + +pci_out_reg ad_iob20 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[20] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[20] ), + .dat_out ( ad_out[20] ) +); + +pci_out_reg ad_iob21 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[21] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[21] ), + .dat_out ( ad_out[21] ) +); + +pci_out_reg ad_iob22 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[22] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[22] ), + .dat_out ( ad_out[22] ) +); + +pci_out_reg ad_iob23 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_mhigh ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[23] ) , + .en_in ( ad_en_ctrl_mhigh ) , + .en_out ( ad_en_out[23] ), + .dat_out ( ad_out[23] ) +); + +pci_out_reg ad_iob24 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[24] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[24] ), + .dat_out ( ad_out[24] ) +); + +pci_out_reg ad_iob25 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[25] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[25] ), + .dat_out ( ad_out[25] ) +); + +pci_out_reg ad_iob26 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[26] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[26] ), + .dat_out ( ad_out[26] ) +); + +pci_out_reg ad_iob27 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[27] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[27] ), + .dat_out ( ad_out[27] ) +); + +pci_out_reg ad_iob28 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[28] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[28] ), + .dat_out ( ad_out[28] ) +); + +pci_out_reg ad_iob29 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[29] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[29] ), + .dat_out ( ad_out[29] ) +); + +pci_out_reg ad_iob30 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[30] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[30] ), + .dat_out ( ad_out[30] ) +); + +pci_out_reg ad_iob31 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( ad_load_ctrl_high ), + .en_en_in ( 1'b1 ), + .dat_in ( temp_ad[31] ) , + .en_in ( ad_en_ctrl_high ) , + .en_out ( ad_en_out[31] ), + .dat_out ( ad_out[31] ) +); + +wire [3:0] cbe_load_ctrl = {4{ master_load_in }} ; +wire [3:0] cbe_en_ctrl = {4{ cbe_en_in }} ; + +pci_out_reg cbe_iob0 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( cbe_load_ctrl[0] ), + .en_en_in ( 1'b1 ), + .dat_in ( cbe_in[0] ) , + .en_in ( cbe_en_ctrl[0] ) , + .en_out ( cbe_en_out[0] ), + .dat_out ( cbe_out[0] ) +); + +pci_out_reg cbe_iob1 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( cbe_load_ctrl[1] ), + .en_en_in ( 1'b1 ), + .dat_in ( cbe_in[1] ) , + .en_in ( cbe_en_ctrl[1] ) , + .en_out ( cbe_en_out[1] ), + .dat_out ( cbe_out[1] ) +); + +pci_out_reg cbe_iob2 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( cbe_load_ctrl[2] ), + .en_en_in ( 1'b1 ), + .dat_in ( cbe_in[2] ) , + .en_in ( cbe_en_ctrl[2] ) , + .en_out ( cbe_en_out[2] ), + .dat_out ( cbe_out[2] ) +); + +pci_out_reg cbe_iob3 +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( cbe_load_ctrl[3] ), + .en_en_in ( 1'b1 ), + .dat_in ( cbe_in[3] ) , + .en_in ( cbe_en_ctrl[3] ) , + .en_out ( cbe_en_out[3] ), + .dat_out ( cbe_out[3] ) +); + +pci_out_reg frame_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( frame_load_in ), + .en_en_in ( 1'b1 ), + .dat_in ( frame_in ) , + .en_in ( frame_en_in ) , + .en_out ( frame_en_out ), + .dat_out ( frame_out ) +); + +pci_out_reg irdy_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( irdy_in ) , + .en_in ( irdy_en_in ) , + .en_out ( irdy_en_out ), + .dat_out ( irdy_out ) +); + +pci_out_reg trdy_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( trdy_in ) , + .en_in ( trdy_en_in ) , + .en_out ( trdy_en_out ), + .dat_out ( trdy_out ) +); + +pci_out_reg stop_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( stop_in ) , + .en_in ( stop_en_in ) , + .en_out ( stop_en_out ), + .dat_out ( stop_out ) +); + +pci_out_reg devsel_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( devsel_in ) , + .en_in ( devsel_en_in ) , + .en_out ( devsel_en_out ), + .dat_out ( devsel_out ) +); + +pci_out_reg par_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( par_in ) , + .en_in ( par_en_in ) , + .en_out ( par_en_out ), + .dat_out ( par_out ) +); + +pci_out_reg perr_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( perr_in ) , + .en_in ( perr_en_in ) , + .en_out ( perr_en_out ), + .dat_out ( perr_out ) +); + +pci_out_reg serr_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( serr_in ) , + .en_in ( serr_en_in ) , + .en_out ( serr_en_out ), + .dat_out ( serr_out ) +); + +pci_out_reg req_iob +( + .reset_in ( reset_in ), + .clk_in ( clk_in) , + .dat_en_in ( 1'b1 ), + .en_en_in ( 1'b1 ), + .dat_in ( req_in ) , + .en_in ( init_complete_in ) , + .en_out ( req_en_out ), + .dat_out ( req_out ) +); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v new file mode 100644 index 000000000..788077dc9 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_io_mux_ad_en_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_io_mux_ad_en_crit.v,v $ +// Revision 1.2 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// + +// module provides equation for ad output enables, which uses critical pci bus inputs + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// module is provided for ad bus output enable Flip-Flops values +module pci_io_mux_ad_en_crit +( + ad_en_in, + pci_frame_in, + pci_trdy_in, + pci_stop_in, + ad_en_out +); +input ad_en_in, + pci_frame_in, + pci_trdy_in, + pci_stop_in ; +output ad_en_out ; + +assign ad_en_out = ad_en_in && ( ~pci_frame_in || (pci_trdy_in && pci_stop_in) ) ; +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v new file mode 100644 index 000000000..4fd91e69e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_io_mux_ad_load_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_io_mux_ad_load_crit.v,v $ +// Revision 1.2 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// module is provided for last level of logic for loading AD output flip-flops +// and output backup flip - flops +module pci_io_mux_ad_load_crit +( + load_in, + load_on_transfer_in, + pci_irdy_in, + pci_trdy_in, + load_out +); + +input load_in, + load_on_transfer_in, + pci_irdy_in, + pci_trdy_in ; + +output load_out ; + +assign load_out = load_in || (load_on_transfer_in && ~pci_irdy_in && ~pci_trdy_in) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v new file mode 100644 index 000000000..d097b9e67 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "irdy_out_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_irdy_out_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// This module is used in master state machine for IRDY output driving + +module pci_irdy_out_crit +( + pci_irdy_out, + irdy_slow_in, + pci_frame_out_in, + pci_trdy_in, + pci_stop_in +) ; + +output pci_irdy_out ; +input irdy_slow_in, + pci_frame_out_in, + pci_trdy_in, + pci_stop_in ; + +assign pci_irdy_out = irdy_slow_in || (pci_frame_out_in && ~(pci_trdy_in && pci_stop_in)) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v new file mode 100644 index 000000000..cc4a169a2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "mas_ad_en_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_mas_ad_en_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// This module is used in master state machine for AD lines output enable driving +module pci_mas_ad_en_crit +( + pci_ad_en_out, + ad_en_slow_in, + ad_en_on_grant_in, + pci_gnt_in +) ; + +output pci_ad_en_out ; +input ad_en_slow_in, + ad_en_on_grant_in, + pci_gnt_in ; + +assign pci_ad_en_out = ad_en_slow_in || (ad_en_on_grant_in && !pci_gnt_in) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v new file mode 100644 index 000000000..6ec59a0c3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v @@ -0,0 +1,70 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "mas_ad_load_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_mas_ad_load_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// module is included for loading output flip - flops by monitoring timing critical GNT pci input +module pci_mas_ad_load_crit +( + ad_load_out, + ad_load_in, + ad_load_on_grant_in, + pci_gnt_in +); +output ad_load_out ; +input ad_load_in, + ad_load_on_grant_in, + pci_gnt_in ; + +assign ad_load_out = ad_load_in || ( ad_load_on_grant_in && !pci_gnt_in ) ; +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v new file mode 100644 index 000000000..d05779aa3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "mas_ch_state_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_mas_ch_state_crit.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// Module is used in master state machine for state machine clock enable driving + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_mas_ch_state_crit +( + change_state_out, + ch_state_med_in, + sm_data_phases_in, + pci_trdy_in, + pci_stop_in +) ; + +output change_state_out ; +input ch_state_med_in, + sm_data_phases_in, + pci_trdy_in, + pci_stop_in ; + +assign change_state_out = ch_state_med_in || sm_data_phases_in && (~(pci_trdy_in && pci_stop_in)) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v new file mode 100644 index 000000000..4787f4bdb --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v @@ -0,0 +1,615 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_master32_sm.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_master32_sm.v,v $ +// Revision 1.5 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.4 2003/01/21 16:06:56 mihad +// Bug fixes, testcases added. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:29 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module includes pci master state machine and surrounding logic + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" + +module pci_master32_sm +( + // system inputs + clk_in, + reset_in, + // arbitration + pci_req_out, + pci_gnt_in, + // master in/outs + pci_frame_in, + pci_frame_out, + pci_frame_out_in, + pci_frame_load_out, + pci_frame_en_in, + pci_frame_en_out, + pci_irdy_in, + pci_irdy_out, + pci_irdy_en_out, + + // target response inputs + pci_trdy_in, + pci_trdy_reg_in, + pci_stop_in, + pci_stop_reg_in, + pci_devsel_in, + pci_devsel_reg_in, + + // address, data, bus command, byte enable in/outs + pci_ad_reg_in, + pci_ad_out, + pci_ad_en_out, + pci_cbe_out, + pci_cbe_en_out, + + // other side of state machine + address_in, + bc_in, + data_in, + data_out, + be_in, + req_in, + rdy_in, + last_in, + next_data_in, + next_be_in, + next_last_in, + ad_load_out, + ad_load_on_transfer_out, + wait_out, + wtransfer_out, + rtransfer_out, + retry_out, + rerror_out, + first_out, + mabort_out, + latency_tim_val_in +) ; + +// system inputs +input clk_in, + reset_in ; + +/*================================================================================================================== +PCI interface signals - bidirectional signals are divided to inputs and outputs in I/O cells instantiation +module. Enables are separate signals. +==================================================================================================================*/ +// arbitration +output pci_req_out ; + +input pci_gnt_in ; + +// master in/outs +input pci_frame_in ; +input pci_frame_en_in ; +input pci_frame_out_in ; + +output pci_frame_out, + pci_frame_en_out ; + +output pci_frame_load_out ; + +input pci_irdy_in ; +output pci_irdy_out, + pci_irdy_en_out; + +// target response inputs +input pci_trdy_in, + pci_trdy_reg_in, + pci_stop_in, + pci_stop_reg_in, + pci_devsel_in, + pci_devsel_reg_in ; + +// address, data, bus command, byte enable in/outs +input [31:0] pci_ad_reg_in ; +output [31:0] pci_ad_out ; + +reg [31:0] pci_ad_out ; + +output pci_ad_en_out ; + +output [3:0] pci_cbe_out ; + +reg [3:0] pci_cbe_out ; + +output pci_cbe_en_out ; + +input [31:0] address_in ; // current request address input + +input [3:0] bc_in ; // current request bus command input + +input [31:0] data_in ; // current dataphase data input + +output [31:0] data_out ; // for read operations - current request data output + +reg [31:0] data_out ; + +input [3:0] be_in ; // current dataphase byte enable inputs + +input req_in ; // initiator cycle is requested +input rdy_in ; // requestor indicates that data is ready to be sent for write transaction and ready to + // be received on read transaction +input last_in ; // last dataphase in current transaction indicator + +// status outputs +output wait_out, // wait indicates to the backend that dataphases are not in progress on PCI bus + wtransfer_out, // on any rising clock edge that this status is 1, data is transferred - heavy constraints here + rtransfer_out, // registered transfer indicator - when 1 indicates that data was transfered on previous clock cycle + retry_out, // retry status output - when target signals a retry + rerror_out, // registered error output - when 1 indicates that error was signalled by a target on previous clock cycle + first_out , // indicates whether or not any data was transfered in current transaction + mabort_out; // master abort indicator + +reg wait_out ; + +// latency timer value input - state machine starts latency timer whenever it starts a transaction and last is not +// asserted ( meaning burst transfer ). +input [7:0] latency_tim_val_in ; + +// next data, byte enable and last inputs +input [31:0] next_data_in ; +input [3:0] next_be_in ; +input next_last_in ; + +// clock enable for data output flip-flops - whenever data is transfered, sm loads next data to those flip flops +output ad_load_out, + ad_load_on_transfer_out ; + +// parameters - states - one hot +// idle state +parameter S_IDLE = 4'h1 ; + +// address state +parameter S_ADDRESS = 4'h2 ; + +// transfer state - dataphases +parameter S_TRANSFER = 4'h4 ; + +// turn arround state +parameter S_TA_END = 4'h8 ; + +// change state - clock enable for sm state register +wire change_state ; +// next state for state machine +reg [3:0] next_state ; +// SM state register +reg [3:0] cur_state ; + +// variables for indicating which state state machine is in +// this variables are used to reduce logic levels in case of heavily constrained PCI signals +reg sm_idle ; +reg sm_address ; +reg sm_data_phases ; +reg sm_turn_arround ; + +// state machine register control logic with clock enable +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + cur_state <= #`FF_DELAY S_IDLE ; + else + if ( change_state ) + cur_state <= #`FF_DELAY next_state ; +end + +// parameters - data selector - ad and bc lines switch between address/data and bus command/byte enable respectively +parameter SEL_ADDR_BC = 2'b01 ; +parameter SEL_DATA_BE = 2'b00 ; +parameter SEL_NEXT_DATA_BE = 2'b11 ; + +reg [1:0] wdata_selector ; + +wire u_dont_have_pci_bus = pci_gnt_in || ~pci_frame_in || ~pci_irdy_in ; // pci master can't start a transaction when GNT is deasserted ( 1 ) or + // bus is not in idle state ( FRAME and IRDY both 1 ) +wire u_have_pci_bus = ~pci_gnt_in && pci_frame_in && pci_irdy_in ; + +// decode count enable - counter that counts cycles passed since address phase +wire sm_decode_count_enable = sm_data_phases ; // counter is enabled when master wants to transfer +wire decode_count_enable = sm_decode_count_enable && pci_trdy_in && pci_stop_in && pci_devsel_in ; // and target is not responding +wire decode_count_load = ~decode_count_enable ; +reg [2:0] decode_count ; + +wire decode_to = ~( decode_count[2] || decode_count[1]) ; + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + // initial value of counter is 4 + decode_count <= #`FF_DELAY 3'h4 ; + else + if ( decode_count_load ) + decode_count <= #`FF_DELAY 3'h4 ; + else + if ( decode_count_enable ) + decode_count <= #`FF_DELAY decode_count - 1'b1 ; +end + +// Bus commands LSbit indicates whether operation is a read or a write +wire do_write = bc_in[0] ; + +// latency timer +reg [7:0] latency_timer ; + +wire latency_time_out = ~( + (latency_timer[7] || latency_timer[6] || latency_timer[5] || latency_timer[4]) || + (latency_timer[3] || latency_timer[2] || latency_timer[1] ) + ) ; + +wire latency_timer_enable = (sm_address || sm_data_phases) && ~latency_time_out ; +wire latency_timer_load = ~sm_address && ~sm_data_phases ; + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + latency_timer <= #`FF_DELAY 8'h00 ; + else + if ( latency_timer_load ) + latency_timer <= #`FF_DELAY latency_tim_val_in ; + else + if ( latency_timer_enable) // latency timer counts down until it expires - then it stops + latency_timer <= #`FF_DELAY latency_timer - 1'b1 ; +end + +// master abort indicators - when decode time out occurres and still no target response is received +wire do_master_abort = decode_to && pci_trdy_in && pci_stop_in && pci_devsel_in ; +reg mabort1 ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + mabort1 <= #`FF_DELAY 1'b0 ; + else + mabort1 <= #`FF_DELAY do_master_abort ; +end + +reg mabort2 ; +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + mabort2 <= #`FF_DELAY 1'b0 ; + else + mabort2 <= #`FF_DELAY mabort1 ; +end + +// master abort is only asserted for one clock cycle +assign mabort_out = mabort1 && ~mabort2 ; + +// register indicating when master should do timeout termination (latency timer expires) +reg timeout ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + timeout <= #`FF_DELAY 1'b0 ; + else + timeout <= #`FF_DELAY (latency_time_out && ~pci_frame_out_in && pci_gnt_in || timeout ) && ~wait_out ; +end + +wire timeout_termination = sm_turn_arround && timeout && pci_stop_reg_in ; + +// frame control logic +// frame is forced to 0 (active) when state machine is in idle state, since only possible next state is address state which always drives frame active +wire force_frame = ~sm_idle ; +// slow signal for frame calculated from various registers in the core +wire slow_frame = last_in || (latency_time_out && pci_gnt_in) || (next_last_in && sm_data_phases) || mabort1 ; +// critical timing frame logic in separate module - some combinations of target signals force frame to inactive state immediately after sampled asserted +// (STOP) +pci_frame_crit frame_iob_feed +( + .pci_frame_out (pci_frame_out), + .force_frame_in (force_frame), + .slow_frame_in (slow_frame), + .pci_stop_in (pci_stop_in) +) ; + +// frame IOB flip flop's clock enable signal +// slow clock enable - calculated from internal - non critical paths +wire frame_load_slow = sm_idle || sm_address || mabort1 ; + +// critical clock enable for frame IOB in separate module - target response signals actually allow frame value change - critical timing +pci_frame_load_crit frame_iob_ce +( + .pci_frame_load_out (pci_frame_load_out), + .sm_data_phases_in (sm_data_phases), + .frame_load_slow_in (frame_load_slow), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in) +) ; + +// IRDY driving +// non critical path for IRDY calculation +wire irdy_slow = pci_frame_out_in && mabort1 || mabort2 ; + +// critical path in separate module +pci_irdy_out_crit irdy_iob_feed +( + .pci_irdy_out (pci_irdy_out), + .irdy_slow_in (irdy_slow), + .pci_frame_out_in (pci_frame_out_in), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in) +) ; + +// transfer FF indicator - when first transfer occurs it is set to 1 so backend can distinguish between disconnects and retries. +wire sm_transfer = sm_data_phases ; +reg transfer ; + +wire transfer_input = sm_transfer && (~(pci_trdy_in || pci_devsel_in) || transfer) ; + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + transfer <= #`FF_DELAY 1'b0 ; + else + transfer <= #`FF_DELAY transfer_input ; +end + +assign first_out = ~transfer ; + +// xfast transfer status output - it's only negated target ready, since wait indicator qualifies valid transfer +assign wtransfer_out = ~pci_trdy_in ; + +// registered transfer status output - calculated from registered target response inputs +assign rtransfer_out = ~(pci_trdy_reg_in || pci_devsel_reg_in) ; + +// registered error status - calculated from registered target response inputs +assign rerror_out = (~pci_stop_reg_in && pci_devsel_reg_in) ; + +// retry is signalled to backend depending on registered target response or when latency timer expires +assign retry_out = timeout_termination || (~pci_stop_reg_in && ~pci_devsel_reg_in) ; + +// AD output flip flops' clock enable +// new data is loaded to AD outputs whenever state machine is idle, bus was granted and bus is in idle state or +// when address phase is about to be finished +wire ad_load_slow = sm_address ; +wire ad_load_on_grant = sm_idle && pci_frame_in && pci_irdy_in ; + +pci_mas_ad_load_crit mas_ad_load_feed +( + .ad_load_out (ad_load_out), + .ad_load_in (ad_load_slow), + .ad_load_on_grant_in (ad_load_on_grant), + .pci_gnt_in (pci_gnt_in) +); + +// next data loading is allowed when state machine is in transfer state and operation is a write +assign ad_load_on_transfer_out = sm_data_phases && do_write ; + +// request for a bus is issued anytime when backend is requesting a transaction and state machine is in idle state +assign pci_req_out = ~(req_in && sm_idle) ; + +// change state signal is actually clock enable for state register +// Non critical path for state change enable: +// state is always changed when: +// - address phase is finishing +// - state machine is in turn arround state +// - state machine is in transfer state and master abort termination is in progress + +wire ch_state_slow = sm_address || sm_turn_arround || sm_data_phases && ( pci_frame_out_in && mabort1 || mabort2 ) ; + +// a bit more critical change state enable is calculated with GNT signal +wire ch_state_med = ch_state_slow || sm_idle && u_have_pci_bus && req_in && rdy_in ; + +// most critical change state enable - calculated from target response signals +pci_mas_ch_state_crit state_machine_ce +( + .change_state_out (change_state), + .ch_state_med_in (ch_state_med), + .sm_data_phases_in (sm_data_phases), + .pci_trdy_in (pci_trdy_in), + .pci_stop_in (pci_stop_in) +) ; + +// ad enable driving +// also divided in several categories - from less critical to most critical in separate module +//wire ad_en_slowest = do_write && (sm_address || sm_data_phases && ~pci_frame_out_in) ; +//wire ad_en_on_grant = sm_idle && pci_frame_in && pci_irdy_in || sm_turn_arround ; +//wire ad_en_slow = ad_en_on_grant && ~pci_gnt_in || ad_en_slowest ; +//wire ad_en_keep = sm_data_phases && do_write && (pci_frame_out_in && ~mabort1 && ~mabort2) ; + +wire ad_en_slow = do_write && ( sm_address || ( sm_data_phases && !( ( pci_frame_out_in && mabort1 ) || mabort2 ) ) ) ; +wire ad_en_on_grant = ( sm_idle && pci_frame_in && pci_irdy_in ) || sm_turn_arround ; + +// critical timing ad enable - calculated from grant input +pci_mas_ad_en_crit ad_iob_oe_feed +( + .pci_ad_en_out (pci_ad_en_out), + .ad_en_slow_in (ad_en_slow), + .ad_en_on_grant_in (ad_en_on_grant), + .pci_gnt_in (pci_gnt_in) +) ; + +// cbe enable driving +wire cbe_en_on_grant = sm_idle && pci_frame_in && pci_irdy_in || sm_turn_arround ; +wire cbe_en_slow = cbe_en_on_grant && ~pci_gnt_in || sm_address || sm_data_phases && ~pci_frame_out_in ; +wire cbe_en_keep = sm_data_phases && pci_frame_out_in && ~mabort1 && ~mabort2 ; + +// most critical cbe enable in separate module - calculated with most critical target inputs +pci_cbe_en_crit cbe_iob_feed +( + .pci_cbe_en_out (pci_cbe_en_out), + .cbe_en_slow_in (cbe_en_slow), + .cbe_en_keep_in (cbe_en_keep), + .pci_stop_in (pci_stop_in), + .pci_trdy_in (pci_trdy_in) + +) ; + +// IRDY enable is equal to FRAME enable delayed for one clock +assign pci_irdy_en_out = pci_frame_en_in ; + +// frame enable driving - sometimes it's calculated from non critical paths +wire frame_en_slow = (sm_idle && u_have_pci_bus && req_in && rdy_in) || sm_address || (sm_data_phases && ~pci_frame_out_in) ; +wire frame_en_keep = sm_data_phases && pci_frame_out_in && ~mabort1 && ~mabort2 ; + +// most critical frame enable - calculated from heavily constrained target inputs in separate module +pci_frame_en_crit frame_iob_en_feed +( + .pci_frame_en_out (pci_frame_en_out), + .frame_en_slow_in (frame_en_slow), + .frame_en_keep_in (frame_en_keep), + .pci_stop_in (pci_stop_in), + .pci_trdy_in (pci_trdy_in) +) ; + +// state machine next state definitions +always@( + cur_state or + do_write or + pci_frame_out_in +) +begin + // default values for state machine outputs + wait_out = 1'b1 ; + wdata_selector = SEL_ADDR_BC ; + sm_idle = 1'b0 ; + sm_address = 1'b0 ; + sm_data_phases = 1'b0 ; + sm_turn_arround = 1'b0 ; + + case ( cur_state ) + + S_IDLE: begin + // indicate the state + sm_idle = 1'b1 ; + // assign next state - only possible is address - if state machine is supposed to stay in idle state + // outside signals disable the clock + next_state = S_ADDRESS ; + wdata_selector = SEL_DATA_BE ; + end + + S_ADDRESS: begin + // indicate the state + sm_address = 1'b1 ; + // select appropriate data/be for outputs + wdata_selector = SEL_NEXT_DATA_BE ; + // only possible next state is transfer state + next_state = S_TRANSFER ; + end + + S_TRANSFER: begin + // during transfers wait indicator is inactive - all status signals are now valid + wait_out = 1'b0 ; + // indicate the state + sm_data_phases = 1'b1 ; + // select appropriate data/be for outputs + wdata_selector = SEL_NEXT_DATA_BE ; + if ( pci_frame_out_in ) + begin + // when frame is inactive next state will be turn arround + next_state = S_TA_END ; + end + else + // while frame is active state cannot be anything else then transfer + next_state = S_TRANSFER ; + end + + S_TA_END: begin + // wait is still inactive because of registered statuses + wait_out = 1'b0 ; + // indicate the state + sm_turn_arround = 1'b1 ; + // next state is always idle + next_state = S_IDLE ; + end + default: next_state = S_IDLE ; + endcase +end + +// ad and cbe lines multiplexer for write data +reg [1:0] rdata_selector ; +always@(posedge clk_in or posedge reset_in) +begin + if ( reset_in ) + rdata_selector <= #`FF_DELAY SEL_ADDR_BC ; + else + if ( change_state ) + rdata_selector <= #`FF_DELAY wdata_selector ; +end + +always@(rdata_selector or address_in or bc_in or data_in or be_in or next_data_in or next_be_in) +begin + case ( rdata_selector ) + SEL_ADDR_BC: begin + pci_ad_out = address_in ; + pci_cbe_out = bc_in ; + end + + SEL_DATA_BE: begin + pci_ad_out = data_in ; + pci_cbe_out = be_in ; + end + SEL_NEXT_DATA_BE, + 2'b10: begin + pci_ad_out = next_data_in ; + pci_cbe_out = next_be_in ; + end + endcase +end + +// data output mux for reads +always@(mabort_out or pci_ad_reg_in) +begin + if ( mabort_out ) + data_out = 32'hFFFF_FFFF ; + else + data_out = pci_ad_reg_in ; +end +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v new file mode 100644 index 000000000..0be11ac4b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v @@ -0,0 +1,846 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_master32_sm_if.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_master32_sm_if.v,v $ +// Revision 1.7 2004/03/19 16:36:55 mihad +// Single PCI Master write fix. +// +// Revision 1.6 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.5 2003/06/12 10:12:22 mihad +// Changed one critical PCI bus signal logic. +// +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:29 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" +`include "bus_commands.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +/*==================================================================== +Module provides interface between PCI bridge internals and PCI master +state machine +====================================================================*/ +module pci_master32_sm_if +( + clk_in, + reset_in, + + // interconnect to pci master state machine + address_out, + bc_out, + data_out, + data_in, + be_out, + req_out, + rdy_out, + last_out, + + next_data_out, + next_be_out, + next_last_out, + + // status inputs from master SM + wait_in, + wtransfer_in, + rtransfer_in, + retry_in, + rerror_in, + first_in , + mabort_in, + + + // WISHBONE WRITE fifo inputs and outputs + wbw_renable_out, + wbw_fifo_addr_data_in, + wbw_fifo_cbe_in, + wbw_fifo_control_in, + wbw_fifo_empty_in, + wbw_fifo_transaction_ready_in, + + // WISHBONE READ fifo inputs and outputs + wbr_fifo_wenable_out, + wbr_fifo_data_out, + wbr_fifo_be_out, + wbr_fifo_control_out, + + // delayed transaction control logic inputs and outputs + del_wdata_in, + del_complete_out, + del_req_in, + del_addr_in, + del_bc_in, + del_be_in, + del_burst_in, + del_error_out, + del_rty_exp_out, + del_we_in, + + // configuration space interconnect + // error reporting + err_addr_out, + err_bc_out, + err_signal_out, + err_source_out, + err_rty_exp_out, + + cache_line_size_in, + + // two signals for pci control and status + mabort_received_out, + tabort_received_out, + + posted_write_not_present_out +); + +// system inputs +input clk_in ; +input reset_in ; + +// PCI master state machine interconnect +output [31:0] address_out ; // address output + +output [3:0] bc_out ; // bus command output +reg [3:0] bc_out ; + +output [31:0] data_out ; // data output for writes +reg [31:0] data_out ; + +input [31:0] data_in ; // data input for reads +output [3:0] be_out ; // byte enable output +reg [3:0] be_out ; + +output req_out ; // request output + +output rdy_out ; // ready output +reg rdy_out ; + +output last_out ; // last data indicator output + +output [31:0] next_data_out ; // next data output +output [3:0] next_be_out ; // next byte enable output +output next_last_out ; // next transfer last indicator + +input wait_in, + wtransfer_in, + rtransfer_in, + retry_in, + rerror_in, + first_in , + mabort_in ; + +// WISHBONE write fifo interconnect +output wbw_renable_out ; // WBW_FIFO read enable signal + +input [31:0] wbw_fifo_addr_data_in ; // WBW_FIFO address/data bus +input [3:0] wbw_fifo_cbe_in ; // WBW_FIFO command/byte enable bus +input [3:0] wbw_fifo_control_in ; // WBW_FIFO control bus +input wbw_fifo_empty_in ; // WBW_FIFO's empty status indicator +input wbw_fifo_transaction_ready_in ; // WBW_FIFO transaction ready indicator + +// WISHBONE read FIFO interconnect +output wbr_fifo_wenable_out ; // write enable for WBR_FIFO + +output [31:0] wbr_fifo_data_out ; // data output to WBR_FIFO + +output [3:0] wbr_fifo_be_out ; // byte enable output for WBR_FIFO + +output [3:0] wbr_fifo_control_out ; // WBR_FIFO control output + +// delayed transaction control logic inputs and outputs +input [31:0] del_wdata_in ; // delayed write data input +output del_complete_out ; // delayed transaction completed output + +input del_req_in ; // delayed transaction request +input [31:0] del_addr_in ; // delayed transaction address +input [3:0] del_bc_in ; // delayed transaction bus command input +input [3:0] del_be_in ; // delayed transaction byte enables input +input del_burst_in ; // delayed transaction burst req. indicator +output del_error_out ; // delayed transation error termination signal + +output del_rty_exp_out ; // retry expired output for delayed transactions + +input del_we_in ; // delayed write request indicator + +output [31:0] err_addr_out ; // erroneous address output +output [3:0] err_bc_out ; // erroneous bus command output + +output err_signal_out ; // error signalization + +output err_source_out ; // error source indicator + +input [7:0] cache_line_size_in ; // cache line size value input + +output err_rty_exp_out ; // retry expired error output + +output mabort_received_out ; // master abort signaled to status register +output tabort_received_out ; // target abort signaled to status register + +output posted_write_not_present_out ; // used in target state machine - must deny read completions when this signal is 0 + + +assign err_bc_out = bc_out ; + +// assign read outputs +/*================================================================================================================== +WISHBONE read FIFO data outputs - just link them to SM data outputs and delayed BE input +==================================================================================================================*/ +assign wbr_fifo_data_out = data_in ; +assign wbr_fifo_be_out = del_be_in ; + +// decode if current bus command is configuration command +wire conf_cyc_bc = ( bc_out[3:1] == `BC_CONF_RW ) ; + +// register for indicating that current data is also last in transfer +reg current_last ; + +// register indicating that last data was transfered OK +reg last_transfered ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + last_transfered <= #`FF_DELAY 1'b0 ; + else + last_transfered <= #`FF_DELAY ~wait_in && last_out && wtransfer_in ; +end + +// status signals output assignement +assign mabort_received_out = mabort_in ; + +wire tabort_ff_in = ~wait_in && rerror_in ; + +reg tabort_received_out ; +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + tabort_received_out <= #`FF_DELAY 1'b0 ; + else + tabort_received_out <= #`FF_DELAY tabort_ff_in ; +end + +// error recovery indicator +reg err_recovery ; + +// operation is locked until error recovery is in progress or error bit is not cleared in configuration space +wire err_lock = err_recovery ; + +// three requests are possible - posted write, delayed write and delayed read +reg del_write_req ; +reg posted_write_req ; +reg del_read_req ; + +// assign request output +assign req_out = del_write_req || posted_write_req || del_read_req ; + +// posted write is not present, when WB Write Fifo is empty and posted write transaction is not beeing requested at present time +assign posted_write_not_present_out = !posted_write_req && wbw_fifo_empty_in ; + +// write requests are staged, so data is read from source into current data register and next data register +reg write_req_int ; +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + write_req_int <= #`FF_DELAY 1'b0 ; + else + write_req_int <= #`FF_DELAY posted_write_req || del_write_req ; + +end + +// ready output is generated one clock after request for reads and two after for writes +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + rdy_out <= #`FF_DELAY 1'b0 ; + else + rdy_out <= #`FF_DELAY del_read_req || ( (posted_write_req || del_write_req) && write_req_int) ; +end + +// wires with logic used as inputs to request FFs +wire do_posted_write = ( wbw_fifo_transaction_ready_in && ~wbw_fifo_empty_in && ~err_lock ) ; +wire do_del = ( del_req_in && ~err_lock && wbw_fifo_empty_in ) ; +wire do_del_write = do_del && del_we_in ; +wire do_del_read = do_del && ~del_we_in ; + +// register for indicating current operation's data source +parameter DELAYED_WRITE = 1'b1 ; +parameter POSTED_WRITE = 1'b0 ; + +// new data source - depending on which transaction will be processed next - delayed read is here because source of byte enables must +// be specified for delayed reads also - data source is not relevant for delayed reads, so value is don't care anyway +wire new_data_source = (do_del_write || do_del_read) ? DELAYED_WRITE : POSTED_WRITE ; // input to data source register +wire data_source_change = ~req_out ; // change (enable) for data source register - when no requests are in progress + +reg data_source ; // data source value +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + // default value is posted write source - wbw_fifo + data_source <= #`FF_DELAY POSTED_WRITE ; + else + if (data_source_change) + // change data source on rising clock edge + data_source <= #`FF_DELAY new_data_source ; +end + +// multiplexer for data output to PCI MASTER state machine +reg [31:0] source_data ; +reg [3:0] source_be ; +always@(data_source or wbw_fifo_addr_data_in or wbw_fifo_cbe_in or del_wdata_in or del_be_in or del_burst_in) +begin + case (data_source) + POSTED_WRITE: begin + source_data = wbw_fifo_addr_data_in ; + source_be = wbw_fifo_cbe_in ; + end + DELAYED_WRITE: begin + source_data = del_wdata_in ; + // read all bytes during delayed burst read! + source_be = ~( del_be_in | {4{del_burst_in}} ) ; + end + endcase +end + +wire waddr = wbw_fifo_control_in[`ADDR_CTRL_BIT] ; + +// address change indicator - address is allowed to be loaded only when no transaction is in progress! +wire address_change = ~req_out ; // address change - whenever there is no request in progress + +// new address - input to register storing address of current request - if posted write request will be next, +// load address and bus command from wbw_fifo, else load data from delayed transaction logic +wire [31:0] new_address = ( ~req_out && do_posted_write ) ? wbw_fifo_addr_data_in[31:0] : del_addr_in[31:0] ; +wire [3:0] new_bc = ( ~req_out && do_posted_write ) ? wbw_fifo_cbe_in : del_bc_in ; + +// address counter enable - only for posted writes when data is actually transfered +wire addr_count_en = !wait_in && posted_write_req && rtransfer_in ; + +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + bc_out <= #`FF_DELAY `BC_RESERVED0 ; + else + if (address_change) + bc_out <= #`FF_DELAY new_bc ; +end + +reg [29:0] current_dword_address ; + +// DWORD address counter with load +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + current_dword_address <= #`FF_DELAY 30'h0000_0000 ; + else + if (address_change) + current_dword_address <= #`FF_DELAY new_address[31:2] ; + else + if (addr_count_en) + current_dword_address <= #`FF_DELAY current_dword_address + 1'b1 ; +end + +reg [1:0] current_byte_address ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + current_byte_address <= #`FF_DELAY 2'b00 ; + else + if (address_change) + current_byte_address <= #`FF_DELAY new_address[1:0] ; +end + +// byte address generation logic +reg [ 1: 0] generated_byte_adr ; +reg [ 1: 0] pci_byte_adr ; + +always@(be_out) +begin + casex(be_out) + 4'bxxx0:generated_byte_adr = 2'b00 ; + 4'bxx01:generated_byte_adr = 2'b01 ; + 4'bx011:generated_byte_adr = 2'b10 ; + 4'b0111:generated_byte_adr = 2'b11 ; + 4'b1111:generated_byte_adr = 2'b00 ; + endcase +end + +always@(generated_byte_adr or bc_out or current_byte_address) +begin + // for memory access commands, set lower 2 address bits to 0 + if ((bc_out == `BC_MEM_READ) | (bc_out == `BC_MEM_WRITE) | + (bc_out == `BC_MEM_READ_MUL) | (bc_out == `BC_MEM_READ_LN) | + (bc_out == `BC_MEM_WRITE_INVAL)) + begin + pci_byte_adr = 2'b00 ; + end + else if ((bc_out == `BC_IO_WRITE) | (bc_out == `BC_IO_READ)) + begin + pci_byte_adr = generated_byte_adr ; + end + else + begin + pci_byte_adr = current_byte_address ; + end +end + +// address output to PCI master state machine assignment +assign address_out = { current_dword_address, pci_byte_adr } ; + +// the same for erroneous address assignement +assign err_addr_out = { current_dword_address, pci_byte_adr } ; + +// cacheline size counter - for read transaction length control +// cache line count is enabled during burst reads when data is actually transfered +wire read_count_enable = ~wait_in && del_read_req && del_burst_in && wtransfer_in ; + +// cache line counter is loaded when del read request is not in progress +wire read_count_load = ~del_read_req ; + +reg [(`WBR_ADDR_LENGTH - 1):0] max_read_count ; +always@(cache_line_size_in or del_bc_in) +begin + if ( (cache_line_size_in >= `WBR_DEPTH) || (~del_bc_in[1] && ~del_bc_in[0]) ) + max_read_count = `WBR_DEPTH - 1'b1; + else + max_read_count = cache_line_size_in ; +end + +reg [(`WBR_ADDR_LENGTH - 1):0] read_count ; + +// cache line bound indicator - it signals when data for one complete cacheline was read +wire read_bound_comb = ~|(read_count[(`WBR_ADDR_LENGTH - 1):2]) ; +reg read_bound ; +always@(posedge clk_in or posedge reset_in) +begin + if ( reset_in ) + read_bound <= #`FF_DELAY 1'b0 ; + else if (read_count_load) + read_bound <= #`FF_DELAY 1'b0 ; + else if ( read_count_enable ) + read_bound <= #`FF_DELAY read_bound_comb ; +end + +wire read_count_change_val = read_count_load | read_count_enable ; + +wire [(`WBR_ADDR_LENGTH - 1):0] read_count_next = read_count_load ? max_read_count : (read_count - 1'b1) ; + +// down counter with load +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + read_count <= #`FF_DELAY 0 ; + else +/* if (read_count_load) + read_count <= #`FF_DELAY max_read_count ; + else + if (read_count_enable) + read_count <= #`FF_DELAY read_count - 1'b1 ; +*/ if (read_count_change_val) + read_count <= #`FF_DELAY read_count_next ; +end + +// flip flop indicating error recovery is in progress +reg err_recovery_in ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + err_recovery <= #`FF_DELAY 1'b0 ; + else + err_recovery <= #`FF_DELAY err_recovery_in ; +end + +/*// retry counter implementation +reg [7:0] retry_count ; + +wire retry_expired = ~|(retry_count[7:1]) ; + +// loading of retry counter - whenever no request is present or other termination than retry or wait is signalled +wire retry_load = ~req_out || (~wait_in && rtransfer_in) ; + +// retry DOWN counter with load +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + retry_count <= #`FF_DELAY 8'hFF ; + else + if ( retry_load ) + retry_count <= #`FF_DELAY `PCI_RTY_CNT_MAX ; + else + if (retry_in) + retry_count <= #`FF_DELAY retry_count - 1'b1 ; +end*/ + +/*================================================================================================================== +Delayed write requests are always single transfers! +Delayed write request starts, when no request is currently beeing processed and it is signaled from other side +of the bridge. +==================================================================================================================*/ +// delayed write request FF input control +reg del_write_req_input ; + +always@( + do_del_write or + del_write_req or + posted_write_req or + del_read_req or + wait_in or + //retry_in or + //retry_expired or + rtransfer_in or + rerror_in or + mabort_in +) +begin + if (~del_write_req) + begin + // delayed write is not in progress and is requested + // delayed write can be requested when no other request is in progress + del_write_req_input = ~posted_write_req && ~del_read_req && do_del_write ; + end + else + begin + // delayed write request is in progress - assign input + del_write_req_input = wait_in || + ( /*~( retry_in && retry_expired) &&*/ + ~rtransfer_in && ~rerror_in && ~mabort_in + ); + end +end + +// delayed write request FLIP-FLOP +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + del_write_req <= #`FF_DELAY 1'b0 ; + else + del_write_req <= #`FF_DELAY del_write_req_input ; +end + +/*================================================================================================ +Posted write request indicator. +Posted write starts whenever no request is in progress and one whole posted write is +stored in WBW_FIFO. It ends on error terminations ( master, target abort, retry expired) or +data transfer terminations if last data is on top of FIFO. +Continues on wait, retry, and disconnect without data. +================================================================================================*/ +// posted write request FF input control +reg posted_write_req_input ; +always@( + do_posted_write or + del_write_req or + posted_write_req or + del_read_req or + wait_in or + //retry_in or + rerror_in or + mabort_in or + //retry_expired or + rtransfer_in or + last_transfered +) +begin + if (~posted_write_req) + begin + // posted write is not in progress + posted_write_req_input = ~del_write_req && ~del_read_req && do_posted_write ; + end + else + begin + posted_write_req_input = wait_in || + (/*~(retry_in && retry_expired && ~rtransfer_in) &&*/ + ~rerror_in && ~mabort_in && + ~(last_transfered) + ) ; + + end +end + +// posted write request flip flop +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + posted_write_req <= #`FF_DELAY 1'b0 ; + else + posted_write_req <= #`FF_DELAY posted_write_req_input ; + +end + +/*================================================================================================ +Delayed read request indicator. +Delayed read starts whenever no request is in progress and delayed read request is signaled from +other side of bridge. It ends on error terminations ( master, target abort, retry expired) or +data transfer terminations if it is not burst transfer or on cache line bounds on burst transfer. +It also ends on disconnects. +Continues on wait and retry. +================================================================================================*/ +// delayed read FF input control +reg del_read_req_input ; +always@( + do_del_read or + del_write_req or + posted_write_req or + del_read_req or + last_transfered or + wait_in or + retry_in or + //retry_expired or + mabort_in or + rtransfer_in or + rerror_in or + first_in or + del_complete_out +) +begin + if (~del_read_req) + begin + del_read_req_input = ~del_write_req && ~posted_write_req && ~del_complete_out && do_del_read ; + end + else + begin + del_read_req_input = wait_in || + ( ~(retry_in && (~first_in /*|| retry_expired */)) && + ~mabort_in && ~rerror_in && + ~(last_transfered) + ) ; + end +end + +// delayed read request FF +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + del_read_req <= #`FF_DELAY 1'b0 ; + else + del_read_req <= #`FF_DELAY del_read_req_input ; +end + +// wire indicating last entry of transaction on top of fifo +wire wlast = wbw_fifo_control_in[`LAST_CTRL_BIT] ; + +wire last_int = posted_write_req && wlast || del_write_req ; + +// intermidiate data, byte enable and last registers +reg [31:0] intermediate_data ; +reg [3:0] intermediate_be ; +reg intermediate_last ; + +wire intermediate_enable = ( posted_write_req || del_write_req ) && ( ~write_req_int || (( ~rdy_out || ~wait_in && rtransfer_in ) && ~intermediate_last)) ; + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + begin + intermediate_data <= #`FF_DELAY 32'h0000_0000 ; + intermediate_be <= #`FF_DELAY 4'h0 ; + intermediate_last <= #`FF_DELAY 1'b0 ; + end + else + if ( intermediate_enable ) + begin + intermediate_data <= #`FF_DELAY source_data ; + intermediate_be <= #`FF_DELAY source_be ; + intermediate_last <= #`FF_DELAY last_int ; + end +end + +// multiplexer for next data +reg [31:0] next_data_out ; +reg [3:0] next_be_out ; +reg write_next_last ; +reg [3:0] write_next_be ; + +always@ +( + rtransfer_in or + intermediate_data or + intermediate_be or + intermediate_last or + wbw_fifo_addr_data_in or + wbw_fifo_cbe_in or + wlast or + wait_in +) +begin + if( rtransfer_in & ~wait_in ) + begin + next_data_out = wbw_fifo_addr_data_in ; + write_next_last = wlast ; + write_next_be = wbw_fifo_cbe_in ; + end + else + begin + next_data_out = intermediate_data ; + write_next_last = intermediate_last ; + write_next_be = intermediate_be ; + end +end + +always@(del_read_req or source_be or write_next_be) +begin + if (del_read_req) + next_be_out = source_be ; + else + next_be_out = write_next_be ; +end +/*================================================================================================ +WBW_FIFO read enable - read from WBW_FIFO is performed on posted writes, when data transfer +termination is received - transfer or disconnect with data. Reads are enabled during error +recovery also, since erroneous transaction must be pulled out of FIFO! +================================================================================================*/ +// wbw_fifo read enable input control + +assign wbw_renable_out = ~req_out && (do_posted_write || err_recovery) || + posted_write_req && ( ~write_req_int || (~rdy_out && ~intermediate_last) || (~wait_in && rtransfer_in && ~intermediate_last)) ; + +/*================================================================================================ +WBR_FIFO write enable control - +writes to FIFO are possible only when delayed read request is in progress and data transfer +or error termination is signalled. It is not enabled on retry or disconnect without data. +================================================================================================*/ +// wbr_fifo write enable control - enabled when transfer is in progress and data is transfered or error is signalled +assign wbr_fifo_wenable_out = del_read_req && ~wait_in && ( rtransfer_in || mabort_in || rerror_in ) ; + +/*================================================================================================ +WBR_FIFO control output for identifying data entries. +This is necesary because of prefetched reads, which partially succeed. On error, error entry +gets in to signal it on WISHBONE bus if WISHBONE master reads up to this entry. +================================================================================================*/ +assign wbr_fifo_control_out[`ADDR_CTRL_BIT] = 1'b0 ; +assign wbr_fifo_control_out[`LAST_CTRL_BIT] = last_transfered ; +assign wbr_fifo_control_out[`DATA_ERROR_CTRL_BIT] = rerror_in || (mabort_in && ~conf_cyc_bc) ; +assign wbr_fifo_control_out[`UNUSED_CTRL_BIT] = 1'b0 ; + +// retry expired error for posted writes control +//assign err_rty_exp_out = posted_write_req && ~wait_in && retry_in && retry_expired && ~rtransfer_in; +assign err_rty_exp_out = 1'b0 ; + +// error source and error signal output control logic - only for posted writes +assign err_source_out = mabort_in /*|| err_rty_exp_out*/ ; + +assign err_signal_out = /*err_rty_exp_out || */ posted_write_req && ~wait_in && (mabort_in || rerror_in) ; + +//assign del_rty_exp_out = (~wait_in && (del_read_req || del_write_req)) && (retry_in && retry_expired && ~rtransfer_in) ; +assign del_rty_exp_out = 1'b0 ; + +assign del_error_out = ~wait_in && (del_write_req || del_read_req) && ( (mabort_in && ~conf_cyc_bc) || rerror_in ) ; + +wire del_write_complete = del_write_req && ~wait_in && ( rtransfer_in || rerror_in || mabort_in ) ; +wire del_read_complete = del_read_req && ~wait_in && ( rerror_in || mabort_in || last_transfered || ( retry_in && ~first_in ) ) ; + +assign del_complete_out = ~wait_in && ( del_write_complete || del_read_complete ) ; + +// next last output generation +assign next_last_out = del_write_req || del_read_req && ( ~del_burst_in || read_bound ) || posted_write_req && ( write_next_last ) ; +/*================================================================================================================== +Error recovery FF gets a value of one, when during posted write error occurs. It is cleared when all the data provided +for erroneous transaction is pulled out of WBW_FIFO +==================================================================================================================*/ + +// error recovery flip flop input - used when posted write is terminated with an error +always@( + err_recovery or + last_out or + wlast or + err_signal_out or + intermediate_last +) +begin + // when error recovery is not set - drive its input so it gets set + if ( ~err_recovery ) + err_recovery_in = ~last_out && ~intermediate_last && err_signal_out ; + else + // when error recovery is set, wbw_fifo is enabled - clear err_recovery when last data entry of erroneous transaction is pulled out of fifo + err_recovery_in = ~wlast ; +end + +wire data_out_load = (posted_write_req || del_write_req) && ( !rdy_out || ( !wait_in && rtransfer_in ) ) ; + +wire be_out_load = (req_out && !rdy_out) || ( posted_write_req && !wait_in && rtransfer_in ) ; + +wire last_load = req_out && ( ~rdy_out || ~wait_in && wtransfer_in ) ; + +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + data_out <= #`FF_DELAY 32'h0000_0000 ; + else + if ( data_out_load ) + data_out <= #`FF_DELAY intermediate_data ; +end + +always@(posedge clk_in or posedge reset_in) +begin + if ( reset_in ) + be_out <= #`FF_DELAY 4'hF ; + else + if ( be_out_load ) + be_out <= #`FF_DELAY posted_write_req ? intermediate_be : source_be ; +end + +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + current_last <= #`FF_DELAY 1'b0 ; + else + if ( last_load ) + current_last <= #`FF_DELAY next_last_out ; +end + +assign last_out = current_last ; +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v new file mode 100644 index 000000000..81a5ff200 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "out_reg.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_out_reg.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// module inferes a single IOB output block as known in FPGA architectures +// It provides data flip flop with clock enable and output enable flip flop with clock enable +// This is tested in Xilinx FPGA - active low output enable +// Check polarity of output enable flip flop for specific architecure. +module pci_out_reg +( + reset_in, + clk_in, + dat_en_in, + en_en_in, + dat_in, + en_in, + en_out, + dat_out +); + +input reset_in, + clk_in, + dat_en_in, + en_en_in, + dat_in, + en_in ; + +output dat_out ; +output en_out ; + +reg dat_out, + en_out ; + +`ifdef ACTIVE_LOW_OE +wire en = ~en_in ; +`else +`ifdef ACTIVE_HIGH_OE +wire en = en_in ; +`endif +`endif + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + dat_out <= #`FF_DELAY 1'b0 ; + else if ( dat_en_in ) + dat_out <= #`FF_DELAY dat_in ; +end + +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + `ifdef ACTIVE_LOW_OE + en_out <= #`FF_DELAY 1'b1 ; + `else + `ifdef ACTIVE_HIGH_OE + en_out <= #`FF_DELAY 1'b0 ; + `endif + `endif + else if ( en_en_in ) + en_out <= #`FF_DELAY en ; +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v new file mode 100644 index 000000000..c55966c28 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v @@ -0,0 +1,90 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "par_crit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_par_crit.v,v $ +// Revision 1.2 2003/02/13 18:26:33 mihad +// Cleaned up the code. No functional changes. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// this one is used in parity generator/checker for calculating parity signal + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_par_crit +( + par_out, + par_out_in, + pci_cbe_en_in, + data_par_in, + pci_cbe_in +) ; + +output par_out ; + +input par_out_in, + pci_cbe_en_in, + data_par_in ; + +input [3:0] pci_cbe_in ; + +assign par_out = pci_cbe_en_in ? par_out_in : ( pci_cbe_in[3] ^ pci_cbe_in[2] ^ pci_cbe_in[1] ^ pci_cbe_in[0] ^ data_par_in) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v new file mode 100644 index 000000000..529c3f311 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v @@ -0,0 +1,336 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_parity_check.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_parity_check.v,v $ +// Revision 1.6 2003/02/13 18:26:33 mihad +// Cleaned up the code. No functional changes. +// +// Revision 1.5 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.4 2002/08/13 11:03:53 mihad +// Added a few testcases. Repaired wrong reset value for PCI_AM5 register. Repaired Parity Error Detected bit setting. Changed PCI_AM0 to always enabled(regardles of PCI_AM0 define), if image 0 is used as configuration image +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" +`include "bus_commands.v" + +module pci_parity_check +( + reset_in, + clk_in, + pci_par_in, + pci_par_out, + pci_par_en_out, + pci_perr_in, + pci_perr_out, + pci_perr_out_in, + pci_perr_en_out, + pci_serr_en_in, + pci_serr_out, + pci_serr_out_in, + pci_serr_en_out, + pci_frame_reg_in, + pci_frame_en_in, + pci_irdy_en_in, + pci_irdy_reg_in, + pci_trdy_reg_in, + pci_trdy_en_in, + pci_par_en_in, + pci_ad_out_in, + pci_ad_reg_in, + pci_cbe_in_in, + pci_cbe_reg_in, + pci_cbe_out_in, + pci_cbe_en_in, + pci_ad_en_in, + par_err_response_in, + par_err_detect_out, + perr_mas_detect_out, + + serr_enable_in, + sig_serr_out + +); + +// system inputs +input reset_in ; +input clk_in ; + +// pci signals that are monitored or generated by parity error checker +input pci_par_in ; // pci PAR input +output pci_par_out ; // pci_PAR output +output pci_par_en_out ; // pci PAR enable output +input pci_perr_in ; // PERR# input +output pci_perr_out ; // PERR# output +output pci_perr_en_out ; // PERR# buffer enable output +input pci_serr_en_in ; // SERR enable input +output pci_serr_out ; // SERR# output +input pci_serr_out_in ; // SERR# output value input +input pci_perr_out_in ; // PERR# output value input +output pci_serr_en_out ; // SERR# buffer enable output +input pci_frame_reg_in ; // frame from pci bus input +input pci_frame_en_in ; // frame enable driven by master state machine +input pci_irdy_en_in ; // irdy enable input from PCI master +input pci_irdy_reg_in ; // irdy from PCI bus +input pci_trdy_reg_in ; // target ready from PCI bus +input pci_trdy_en_in ; // target ready output enable +input pci_par_en_in ; // par enable input +input [31:0] pci_ad_out_in ; // data driven by bridge to PCI +input [31:0] pci_ad_reg_in ; // data driven by other agents on PCI +input [3:0] pci_cbe_in_in ; // cbe driven by outside agents +input [3:0] pci_cbe_reg_in ; // registered cbe driven by outside agents +input [3:0] pci_cbe_out_in ; // cbe driven by pci master state machine +input pci_ad_en_in ; // ad enable input +input par_err_response_in ; // parity error response bit from conf.space +output par_err_detect_out ; // parity error detected signal out +output perr_mas_detect_out ; // master asserted PERR or sampled PERR asserted +input serr_enable_in ; // system error enable bit from conf.space +output sig_serr_out ; // signalled system error output for configuration space +input pci_cbe_en_in ; + +// FFs for frame input - used for determining whether PAR is sampled for address phase or for data phase +reg frame_dec2 ; +reg check_perr ; + +/*======================================================================================================================= +CBE lines' parity is needed for overall parity calculation +=======================================================================================================================*/ +wire par_cbe_out = pci_cbe_out_in[3] ^ pci_cbe_out_in[2] ^ pci_cbe_out_in[1] ^ pci_cbe_out_in[0] ; +wire par_cbe_in = pci_cbe_reg_in[3] ^ pci_cbe_reg_in[2] ^ pci_cbe_reg_in[1] ^ pci_cbe_reg_in[0] ; + +/*======================================================================================================================= +Parity generator - parity is generated and assigned to output on every clock edge. PAR output enable is active +one clock cycle after data output enable. Depending on whether master is performing access or target is responding, +apropriate cbe data is included in parity generation. Non - registered CBE is used during reads through target SM +=======================================================================================================================*/ + +// generate appropriate par signal +wire data_par = (pci_ad_out_in[31] ^ pci_ad_out_in[30] ^ pci_ad_out_in[29] ^ pci_ad_out_in[28]) ^ + (pci_ad_out_in[27] ^ pci_ad_out_in[26] ^ pci_ad_out_in[25] ^ pci_ad_out_in[24]) ^ + (pci_ad_out_in[23] ^ pci_ad_out_in[22] ^ pci_ad_out_in[21] ^ pci_ad_out_in[20]) ^ + (pci_ad_out_in[19] ^ pci_ad_out_in[18] ^ pci_ad_out_in[17] ^ pci_ad_out_in[16]) ^ + (pci_ad_out_in[15] ^ pci_ad_out_in[14] ^ pci_ad_out_in[13] ^ pci_ad_out_in[12]) ^ + (pci_ad_out_in[11] ^ pci_ad_out_in[10] ^ pci_ad_out_in[9] ^ pci_ad_out_in[8]) ^ + (pci_ad_out_in[7] ^ pci_ad_out_in[6] ^ pci_ad_out_in[5] ^ pci_ad_out_in[4]) ^ + (pci_ad_out_in[3] ^ pci_ad_out_in[2] ^ pci_ad_out_in[1] ^ pci_ad_out_in[0]) ; + +wire par_out_only = data_par ^ par_cbe_out ; + +pci_par_crit par_gen +( + .par_out (pci_par_out), + .par_out_in (par_out_only), + .pci_cbe_en_in (pci_cbe_en_in), + .data_par_in (data_par), + .pci_cbe_in (pci_cbe_in_in) +) ; + +// PAR enable = ad output enable delayed by one clock +assign pci_par_en_out = pci_ad_en_in ; + +/*======================================================================================================================= +Parity checker - parity is checked on every clock cycle. When parity error is detected, appropriate action is taken +to signal address parity errors on SERR if enabled and data parity errors on PERR# if enabled. Logic also drives +outputs to configuration space to set appropriate status bits if parity error is detected. PAR signal is checked on +master read operations or writes through pci target. Master read is performed when master drives irdy output and +doesn't drive ad lines. Writes through target are performed when target is driving trdy and doesn't drive ad lines. +=======================================================================================================================*/ + +// equation indicating whether to check and generate or not PERR# signal on next cycle +wire perr_generate = ~pci_par_en_in && ~pci_ad_en_in // par was not generated on this cycle, so it should be checked + && ((pci_irdy_en_in && ~pci_trdy_reg_in) || // and master is driving irdy and target is signaling ready + (pci_trdy_en_in && ~pci_irdy_reg_in)) ; // or target is driving trdy and master is signaling ready + +wire data_in_par = (pci_ad_reg_in[31] ^ pci_ad_reg_in[30] ^ pci_ad_reg_in[29] ^ pci_ad_reg_in[28]) ^ + (pci_ad_reg_in[27] ^ pci_ad_reg_in[26] ^ pci_ad_reg_in[25] ^ pci_ad_reg_in[24]) ^ + (pci_ad_reg_in[23] ^ pci_ad_reg_in[22] ^ pci_ad_reg_in[21] ^ pci_ad_reg_in[20]) ^ + (pci_ad_reg_in[19] ^ pci_ad_reg_in[18] ^ pci_ad_reg_in[17] ^ pci_ad_reg_in[16]) ^ + (pci_ad_reg_in[15] ^ pci_ad_reg_in[14] ^ pci_ad_reg_in[13] ^ pci_ad_reg_in[12]) ^ + (pci_ad_reg_in[11] ^ pci_ad_reg_in[10] ^ pci_ad_reg_in[9] ^ pci_ad_reg_in[8]) ^ + (pci_ad_reg_in[7] ^ pci_ad_reg_in[6] ^ pci_ad_reg_in[5] ^ pci_ad_reg_in[4]) ^ + (pci_ad_reg_in[3] ^ pci_ad_reg_in[2] ^ pci_ad_reg_in[1] ^ pci_ad_reg_in[0]) ; + +//wire perr = (cbe_par_reg ^ pci_par_in ^ data_in_par) ; +wire perr ; +wire perr_n ; +wire perr_en ; + +assign pci_perr_out = perr_n ; + +// parity error output assignment +//assign pci_perr_out = ~(perr && perr_generate) ; + +wire non_critical_par = par_cbe_in ^ data_in_par ; + +pci_perr_crit perr_crit_gen +( + .perr_out (perr), + .perr_n_out (perr_n), + .non_critical_par_in(non_critical_par), + .pci_par_in (pci_par_in), + .perr_generate_in (perr_generate) +) ; + +// PERR# enable +wire pci_perr_en_reg ; +pci_perr_en_crit perr_en_crit_gen +( + .reset_in (reset_in), + .clk_in (clk_in), + .perr_en_out (pci_perr_en_out), + .perr_en_reg_out (pci_perr_en_reg), + .non_critical_par_in (non_critical_par), + .pci_par_in (pci_par_in), + .perr_generate_in (perr_generate), + .par_err_response_in (par_err_response_in) +) ; + +// address phase decoding +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + frame_dec2 <= #`FF_DELAY 1'b0 ; + else + frame_dec2 <= #`FF_DELAY pci_frame_reg_in ; +end + +// address phase parity error checking - done after address phase is detected - which is - when bridge's master is not driving frame, +// frame was asserted on previous cycle and was not asserted two cycles before. +wire check_for_serr_on_first = ~pci_frame_reg_in && frame_dec2 && ~pci_frame_en_in ; + +reg check_for_serr_on_second ; +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + check_for_serr_on_second <= #`FF_DELAY 1'b0 ; + else + check_for_serr_on_second <= #`FF_DELAY check_for_serr_on_first && ( pci_cbe_reg_in == `BC_DUAL_ADDR_CYC ) ; +end + +wire check_for_serr = check_for_serr_on_first || check_for_serr_on_second ; + +wire serr_generate = check_for_serr && serr_enable_in && par_err_response_in ; + +pci_serr_en_crit serr_en_crit_gen +( + .serr_en_out (pci_serr_en_out), + .pci_par_in (pci_par_in), + .non_critical_par_in(non_critical_par), + .serr_generate_in (serr_generate) +); + + +// serr is enabled only for reporting errors - route this signal to configuration space +assign sig_serr_out = pci_serr_en_in ; + +// SERR# output is always 0, just enable is driven apropriately +pci_serr_crit serr_crit_gen +( + .serr_out (pci_serr_out), + .non_critical_par_in (non_critical_par), + .pci_par_in (pci_par_in), + .serr_check_in (check_for_serr) +); + +/*======================================================================================================================================= + Synchronizing mechanism detecting what is supposed to be done - PERR# generation or PERR# checking +=======================================================================================================================================*/ +// perr should be checked one clock after PAR is generated +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + check_perr <= #`FF_DELAY 1'b0 ; + else + check_perr <= #`FF_DELAY pci_par_en_in ; +end + +wire perr_sampled_in = ~pci_perr_in && check_perr ; +reg perr_sampled ; +always@(posedge reset_in or posedge clk_in) +begin + if (reset_in) + perr_sampled <= #`FF_DELAY 1'b0 ; + else + perr_sampled <= #`FF_DELAY perr_sampled_in ; +end + +// assign output for parity error detected bit +assign par_err_detect_out = ~pci_serr_out_in || ~pci_perr_out_in ;//|| perr_sampled ; MihaD - removed - detected parity error is set only during Master Reads or Target Writes + +// FF indicating that that last operation was done as bus master +reg frame_and_irdy_en_prev ; +reg frame_and_irdy_en_prev_prev ; +reg master_perr_report ; +always@(posedge reset_in or posedge clk_in) +begin + if ( reset_in ) + begin + master_perr_report <= #`FF_DELAY 1'b0 ; + frame_and_irdy_en_prev <= #`FF_DELAY 1'b0 ; + frame_and_irdy_en_prev_prev <= #`FF_DELAY 1'b0 ; + end + else + begin + master_perr_report <= #`FF_DELAY frame_and_irdy_en_prev_prev ; + frame_and_irdy_en_prev <= #`FF_DELAY pci_irdy_en_in && pci_frame_en_in ; + frame_and_irdy_en_prev_prev <= #`FF_DELAY frame_and_irdy_en_prev ; + end +end + +assign perr_mas_detect_out = master_perr_report && ( (par_err_response_in && perr_sampled) || pci_perr_en_reg ) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v new file mode 100644 index 000000000..b60573f5d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v @@ -0,0 +1,201 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_decoder.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_pci_decoder.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_pci_decoder (hit, addr_out, + addr_in, bc_in, + base_addr, mask_addr, tran_addr, at_en, + mem_io_space, mem_en, io_en) ; + +// Decoding address size parameter - for FPGAs 1MegByte is recommended +// MAXIMUM is 20 (4KBytes), length 12 is 1 MByte !!! +parameter decode_len = 12 ; + +//########################################################################################################### +// ALL COMMENTS are written as there were decode_len 20. This number and 12 (32 - 20) are assigning the +// numbers of decoded and compared bits, etc. +//########################################################################################################### + +/*----------------------------------------------------------------------------------------------------------- +DECODER interface decodes input address (ADDR_IN); what means that it validates (HIT), if input address +falls within the defined image space boundaries. Image space boundarie is defined with image base address +register (BASE_ADDR) and address mask register (MASK_ADDR). +Beside that, it also translates (maps) the input address to the output address (ADDR_OUT), regarding the +translation address register (TRAN_ADDR) and the address mask register. +-----------------------------------------------------------------------------------------------------------*/ + +// output control +output hit ; +// output address +output [31:0] addr_out ; +// input address and bus command +input [31:0] addr_in ; +input [3:0] bc_in ; + +// input registers - 12 LSbits are not valid since the smallest possible size is 4KB ! +input [31:(32-decode_len)] base_addr ; +input [31:(32-decode_len)] mask_addr ; +input [31:(32-decode_len)] tran_addr ; + +// input bit[2] of the Image Control register used to enable the address translation ! +input at_en ; + +// memory or io space selection and its enable signals ! +input mem_io_space ; +input mem_en ; +input io_en ; + +/*----------------------------------------------------------------------------------------------------------- +Internal signals ! +-----------------------------------------------------------------------------------------------------------*/ + +// bit[31] if address mask register is IMAGE ENABLE bit (img_en) +wire img_en ; + +// addr_in_compare are masked input address bits that are compared with masked base_addr +wire [31:(32-decode_len)] addr_in_compare ; +// base_addr_compare are masked base address bits that are compared with masked addr_in +wire [31:(32-decode_len)] base_addr_compare ; + +/*----------------------------------------------------------------------------------------------------------- +Decoding the input address! +This logic produces the loghest path in this module! + +20 MSbits of input addres are as well as base address (20 bits) masked with corrected address mask. Only +masked bits of each vector are actually logically compared. +Bit[31] of address mask register is used to enable the image space ! +Because of PCI bus specifications, there is also the comparison of memory/io selection (mem_io_space) and +its appropriate enable bit (mem_en / io_en). +-----------------------------------------------------------------------------------------------------------*/ + +assign addr_in_compare = (addr_in[31:(32-decode_len)] & mask_addr) ; + +assign base_addr_compare = (base_addr & mask_addr) ; + +assign img_en = mask_addr[31] ; + +wire addr_hit = (addr_in_compare == base_addr_compare) ; + +wire space_hit = (!mem_io_space && mem_en && img_en) || (mem_io_space && io_en && img_en) ; + +reg bc_hit ; +always@(bc_in or mem_io_space) +begin // Allowed bus commands for accesses through IMAGEs to WB bus - BC_CONF_WRITE/READ are not used with address claim!!! + case ( {bc_in[3:1], mem_io_space} ) + 4'b001_1, // BC_IO_READ or BC_IO_WRITE and IO space + 4'b011_0, // BC_MEM_READ or BC_MEM_WRITE and MEM space + 4'b110_0, // BC_MEM_READ_MUL and MEM space - BC_DUAL_ADDR_CYC must NOT be allowed! + 4'b111_0: // BC_MEM_READ_LN or BC_MEM_WRITE_INVAL and MEM space + bc_hit <= 1'b1 ; + default: + bc_hit <= 1'b0 ; + endcase +end + +wire bc_forbid = bc_in[3] && bc_in[2] && !bc_in[1] && bc_in[0] ; // BC_DUAL_ADDR_CYC must NOT be allowed! + + +assign hit = (addr_hit && space_hit && bc_hit && !bc_forbid) ; + +/*----------------------------------------------------------------------------------------------------------- +Translating the input address! + +Translation of input address is not implemented if ADDR_TRAN_IMPL is not defined + +20 MSbits of input address are masked with negated value of the corrected address mask in order to get +address bits of the input address which won't be replaced with translation address bits. +Translation address bits (20 bits) are masked with corrected address mask. Only masked bits of vector are +actually valid, all others are zero. +Boath vectors are bit-wise ORed in order to get the valid translation address with an offset of an input +address. +12 LSbits of an input address are assigned to 12 LSbits of an output addres. +-----------------------------------------------------------------------------------------------------------*/ + +`ifdef ADDR_TRAN_IMPL + // if Address Translation Enable bit is set, then translation address is used othervise input address is used! + // addr_in_combine input address bits are not replaced with translation address! + wire [31:(32-decode_len)] addr_in_combine ; + // tran_addr_combine are masked and combined with addr_in_combine! + reg [31:(32-decode_len)] tran_addr_combine ; + + assign addr_in_combine = (addr_in[31:(32-decode_len)] & ~mask_addr) ; + always@(at_en or tran_addr or mask_addr or addr_in) + begin + if (at_en) + begin + tran_addr_combine <= (tran_addr & mask_addr) ; + end + else + begin + tran_addr_combine <= (addr_in[31:(32-decode_len)] & mask_addr) ; + end + end + + assign addr_out[31:(32-decode_len)] = (addr_in_combine | tran_addr_combine) ; + assign addr_out[(31-decode_len):0] = addr_in [(31-decode_len):0] ; +`else + assign addr_out = addr_in ; +`endif + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v new file mode 100644 index 000000000..5bc4ca987 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v @@ -0,0 +1,464 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Generic Two-Port Synchronous RAM //// +//// //// +//// This file is part of pci bridge project //// +//// http://www.opencores.org/cvsweb.shtml/pci/ //// +//// //// +//// Description //// +//// This block is a wrapper with common two-port //// +//// synchronous memory interface for different //// +//// types of ASIC and FPGA RAMs. Beside universal memory //// +//// interface it also provides behavioral model of generic //// +//// two-port synchronous RAM. //// +//// It should be used in all OPENCORES designs that want to be //// +//// portable accross different target technologies and //// +//// independent of target memory. //// +//// //// +//// Supported ASIC RAMs are: //// +//// - Artisan Double-Port Sync RAM //// +//// - Avant! Two-Port Sync RAM (*) //// +//// - Virage 2-port Sync RAM //// +//// //// +//// Supported FPGA RAMs are: //// +//// - Xilinx Virtex RAMB4_S16_S16 //// +//// //// +//// To Do: //// +//// - fix Avant! //// +//// - xilinx rams need external tri-state logic //// +//// - add additional RAMs (Altera, VS etc) //// +//// //// +//// Author(s): //// +//// - Damjan Lampret, lampret@opencores.org //// +//// - Miha Dolenc, mihad@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_pci_tpram.v,v $ +// Revision 1.4 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.3 2003/10/17 09:11:52 markom +// mbist signals updated according to newest convention +// +// Revision 1.2 2003/08/14 13:06:03 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.7 2002/10/18 03:36:37 tadejm +// Changed wrong signal name mbist_sen into mbist_ctrl_i. +// +// Revision 1.6 2002/10/17 22:51:08 tadejm +// Changed BIST signals for RAMs. +// +// Revision 1.5 2002/10/11 10:09:01 mihad +// Added additional testcase and changed rst name in BIST to trst +// +// Revision 1.4 2002/10/08 17:17:06 mihad +// Added BIST signals for RAMs. +// +// Revision 1.3 2002/09/30 17:22:27 mihad +// Added support for Virtual Silicon two port RAM. Didn't run regression on it yet! +// +// Revision 1.2 2002/08/19 16:51:36 mihad +// Extracted distributed RAM module from wb/pci_tpram.v to its own file, got rid of undef directives +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" + +module pci_pci_tpram +( + // Generic synchronous two-port RAM interface + clk_a, + rst_a, + ce_a, + we_a, + oe_a, + addr_a, + di_a, + do_a, + clk_b, + rst_b, + ce_b, + we_b, + oe_b, + addr_b, + di_b, + do_b +`ifdef PCI_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif +); + +// +// Default address and data buses width +// +parameter aw = 8; +parameter dw = 40; + +// +// Generic synchronous two-port RAM interface +// +input clk_a; // Clock +input rst_a; // Reset +input ce_a; // Chip enable input +input we_a; // Write enable input +input oe_a; // Output enable input +input [aw-1:0] addr_a; // address bus inputs +input [dw-1:0] di_a; // input data bus +output [dw-1:0] do_a; // output data bus +input clk_b; // Clock +input rst_b; // Reset +input ce_b; // Chip enable input +input we_b; // Write enable input +input oe_b; // Output enable input +input [aw-1:0] addr_b; // address bus inputs +input [dw-1:0] di_b; // input data bus +output [dw-1:0] do_b; // output data bus + +`ifdef PCI_BIST +// debug chain signals +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +// +// Internal wires and registers +// + +`ifdef PCI_VS_STP + `define PCI_PCI_RAM_SELECTED + `ifdef PCI_BIST + vs_hdtp_64x40_bist i_vs_hdtp_64x40_bist + `else + vs_hdtp_64x40 i_vs_hdtp_64x40 + `endif + ( + .RCK (clk_b), + .WCK (clk_a), + .RADR (addr_b), + .WADR (addr_a), + .DI (di_a), + .DOUT (do_b), + .REN (1'b0), + .WEN (!we_a) + `ifdef PCI_BIST + , + // debug chain signals + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) + `endif + ); + + assign do_a = 0 ; +`endif + +`ifdef PCI_ARTISAN_SDP + `define PCI_PCI_RAM_SELECTED + // + // Instantiation of ASIC memory: + // + // Artisan Synchronous Double-Port RAM (ra2sh) + // + `ifdef PCI_BIST + art_hsdp_64x40_bist /*#(dw, 1<> 1)) + begin + start_sent = 1'b1 ; + sda_oe_en = 1'b1 ; + end + + // after half clock period of driving the sda low, the only possible + // transition is to send state. + // if send bit is not active, stop the procedure - undrive sda + if (clk_gen_cnt == period_cnt) + begin + clk_gen_cnt_clr = 1'b1 ; + if (send_bit) + begin + tx_rx_next_state = tx_rx_send_bits ; + end + else + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + tx_rx_next_state = tx_rx_idle ; + end + end + end + + tx_rx_send_bits: + begin + clk_gen_cnt_en = 1'b1 ; + + // generate high to low transition on the scl line immediately + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, load new value for sda oe, depending on the + // msb bit in the shift register + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = ~tx_shift_reg[7] ; + sda_oe_en = 1'b1 ; + bit_sent = 1'b1 ; + end + + // after clock low time, generate low to high transition on the scl line + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after clock high time, check what to do next + if (clk_gen_cnt == (period_cnt)) + begin + clk_gen_cnt_clr = 1'b1 ; + + if (~send_bit) + begin + // after transmiting all the bits, the only possible transition is to the state + // that checks the eprom acknowledge + if (rec_ack) + tx_rx_next_state = tx_rx_rec_ack ; + else + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + tx_rx_next_state = tx_rx_idle ; + end + end + end + end + + tx_rx_rec_bits: + begin + clk_gen_cnt_en = 1'b1 ; + sda_i_reg_en = 1'b1 ; + + // generate high to low transition on the scl line immediately + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, disable sda driver + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + end + + // after clock low time, generate low to high transition on the scl line + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock high time, report received bit + if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) ) + begin + bit_rec = 1'b1 ; + end + + // after clock period is finished, check the next operation + if (clk_gen_cnt == (period_cnt)) + begin + clk_gen_cnt_clr = 1'b1 ; + + if (~rec_bit) + begin + // when all bits are received, only nack or ack next states are possible + if (send_ack) + tx_rx_next_state = tx_rx_send_ack ; + else if (send_nack) + tx_rx_next_state = tx_rx_send_nack ; + else + begin + tx_rx_next_state = tx_rx_idle ; + end + end + end + end + + tx_rx_send_ack: + begin + clk_gen_cnt_en = 1'b1 ; + + // generate high to low transition on the scl line + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, enable the sda driver + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b1 ; + sda_oe_en = 1'b1 ; + ack_sent = 1'b1 ; + end + + // after clock low time, disable the scl driver - generate low to high transition on the scl line + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after clock period time expires, check what to do next + if (clk_gen_cnt == period_cnt) + begin + clk_gen_cnt_clr = 1'b1 ; + + // after the byte is acknowledged, the only possible next state is receive bits + // state + if (rec_bit) + tx_rx_next_state = tx_rx_rec_bits ; + else + begin + // this should never happen + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + + tx_rx_next_state = tx_rx_idle ; + end + end + end + + tx_rx_rec_ack: + begin + + clk_gen_cnt_en = 1'b1 ; + sda_i_reg_en = 1'b1 ; + + // generate high to low transition on the scl line + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, disable the sda driver + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + end + + // after clock low time, disable the scl driver - generate low to high transition on the scl line + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after 1/2 clock high time, report ack or nack condition, depending on the sda input state + if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) ) + begin + ack_rec = ~sda_i_reg ; + nack_rec = sda_i_reg ; + end + + // after clock period time expires, check what to do next + if (clk_gen_cnt == period_cnt) + begin + clk_gen_cnt_clr = 1'b1 ; + + if (send_bit) + tx_rx_next_state = tx_rx_send_bits ; + else if (rec_bit) + tx_rx_next_state = tx_rx_rec_bits ; + else if (send_stop) + tx_rx_next_state = tx_rx_stop ; + else if (send_start) + tx_rx_next_state = tx_rx_restart ; + else + begin + // this should never happen + tx_rx_next_state = tx_rx_idle ; + end + end + end + + tx_rx_send_nack: + begin + clk_gen_cnt_en = 1'b1 ; + + // generate high to low transition on the scl line + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, disable the sda driver + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + nack_sent = 1'b1 ; + end + + // after clock low time, disable the scl driver - generate low to high transition on the scl line + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after clock period time expires, check what to do next + if (clk_gen_cnt == period_cnt) + begin + clk_gen_cnt_clr = 1'b1 ; + + // after the no acknowledge is sent, the only possible next state is stop + // state + if (send_stop) + tx_rx_next_state = tx_rx_stop ; + else + begin + // this should never happen + tx_rx_next_state = tx_rx_idle ; + end + end + end + + tx_rx_restart: + begin + clk_gen_cnt_en = 1'b1 ; + + // generate high to low transition + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, release sda line + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + end + + // generate low to high transition + if (clk_gen_cnt == (period_cnt >> 1)) + begin + clk_gen_cnt_clr = 1'b1 ; + + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + + if (send_start) + tx_rx_next_state = tx_rx_start ; + else + tx_rx_next_state = tx_rx_idle ; + end + end + + tx_rx_stop: + begin + clk_gen_cnt_en = 1'b1 ; + + // generate high to low transition + if (clk_gen_cnt == 'h0) + begin + scl_oe = 1'b1 ; + scl_oe_en = 1'b1 ; + end + + // after half of clock low time, drive sda line low + if (clk_gen_cnt == (period_cnt >> 2)) + begin + sda_oe = 1'b1 ; + sda_oe_en = 1'b1 ; + end + + // generate low to high transition + if (clk_gen_cnt == (period_cnt >> 1)) + begin + scl_oe = 1'b0 ; + scl_oe_en = 1'b1 ; + end + + // after full clock period, release the sda line + if (clk_gen_cnt == period_cnt) + begin + sda_oe = 1'b0 ; + sda_oe_en = 1'b1 ; + stop_sent = 1'b1 ; + + tx_rx_next_state = tx_rx_idle ; + end + end + + endcase +end + +reg [rw_seq_state_width - 1:0] rw_seq_state ; + +reg doing_read , + doing_write , + doing_seq_read , + adr_set ; + +reg [ 3: 0] bits_transfered ; + +always@(posedge clk_i or posedge reset_i) +begin + if (reset_i) + begin + rw_seq_state <= rw_seq_idle ; + adr_set <= 1'b0 ; + doing_read <= 1'b0 ; + doing_write <= 1'b0 ; + doing_seq_read <= 1'b0 ; + dat_o <= 'h0 ; + tx_shift_reg <= 'h0 ; + send_start <= 'h0 ; + send_stop <= 'h0 ; + send_bit <= 'h0 ; + send_nack <= 'h0 ; + rec_ack <= 'h0 ; + no_ack_o <= 'h0 ; + bits_transfered <= 'h0 ; + write_done_o <= 'h0 ; + dat_rdy_o <= 'h0 ; + send_ack <= 'h0 ; + rec_bit <= 'h0 ; + end + else + begin + + case (rw_seq_state) + + rw_seq_idle: + begin + tx_shift_reg <= {4'b1010, adr_i[10: 8], 1'b0} ; + adr_set <= 1'b0 ; + + if ( tx_rx_sm_idle & ~(doing_write | doing_read | doing_seq_read) ) + begin + if (do_write_i | do_rnd_read_i | do_seq_read_i) + begin + rw_seq_state <= rw_seq_tx_ctrl ; + send_start <= 1'b1 ; + end + + if (do_write_i) + doing_write <= 1'b1 ; + else if (do_rnd_read_i) + doing_read <= 1'b1 ; + else if (do_seq_read_i) + doing_seq_read <= 1'b1 ; + end + else + begin + doing_write <= 1'b0 ; + doing_read <= 1'b0 ; + doing_seq_read <= 1'b0 ; + end + end + + rw_seq_tx_ctrl: + begin + if (send_start) + begin + bits_transfered <= 'h0 ; + + if (start_sent) + begin + send_start <= 1'b0 ; + send_bit <= 1'b1 ; + end + end + else if (send_bit) + begin + if (bit_sent) + begin + bits_transfered <= bits_transfered + 1'b1 ; + tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; + end + + if (bits_transfered == 'h8) + begin + send_bit <= 1'b0 ; + rec_ack <= 1'b1 ; + end + end + else if (rec_ack) + begin + bits_transfered <= 'h0 ; + + if (ack_rec | nack_rec) + rec_ack <= 1'b0 ; + + if (ack_rec) + begin + if (doing_write | ~adr_set) + begin + rw_seq_state <= rw_seq_tx_adr ; + tx_shift_reg <= adr_i[ 7: 0] ; + send_bit <= 1'b1 ; + end + else + begin + rw_seq_state <= rw_seq_rx_byte ; + rec_bit <= 1'b1 ; + end + end + else if (nack_rec) + begin + no_ack_o <= 1'b1 ; + send_stop <= 1'b1 ; + end + end + else if (send_stop) + begin + no_ack_o <= 1'b0 ; + + if (stop_sent) + begin + send_stop <= 1'b0 ; + rw_seq_state <= rw_seq_idle ; + end + end + end + + rw_seq_tx_adr: + begin + if (send_bit) + begin + if (bit_sent) + begin + bits_transfered <= bits_transfered + 1'b1 ; + tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; + end + + if (bits_transfered == 'h8) + begin + send_bit <= 1'b0 ; + rec_ack <= 1'b1 ; + end + end + else if (rec_ack) + begin + bits_transfered <= 'h0 ; + + if (ack_rec | nack_rec) + rec_ack <= 1'b0 ; + + if (ack_rec) + begin + + adr_set <= 1'b1 ; + + if (doing_write) + begin + send_bit <= 1'b1 ; + rw_seq_state <= rw_seq_tx_byte ; + tx_shift_reg <= dat_i ; + end + else if (doing_read | doing_seq_read) + begin + send_start <= 1'b1 ; + rw_seq_state <= rw_seq_tx_ctrl ; + tx_shift_reg <= 8'b10100001 ; + end + end + else if (nack_rec) + begin + no_ack_o <= 1'b1 ; + send_stop <= 1'b1 ; + end + end + else if (send_stop) + begin + no_ack_o <= 1'b0 ; + + if (stop_sent) + begin + send_stop <= 1'b0 ; + rw_seq_state <= rw_seq_idle ; + end + end + end + + rw_seq_tx_byte: + begin + if (send_bit) + begin + if (bit_sent) + begin + bits_transfered <= bits_transfered + 1'b1 ; + tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; + end + + if (bits_transfered == 'h8) + begin + send_bit <= 1'b0 ; + rec_ack <= 1'b1 ; + end + end + else if (rec_ack) + begin + bits_transfered <= 'h0 ; + + if (ack_rec | nack_rec) + begin + rec_ack <= 1'b0 ; + send_stop <= 1'b1 ; + end + + if (nack_rec) + no_ack_o <= 1'b1 ; + + if (ack_rec) + write_done_o <= 1'b1 ; + end + else if (send_stop) + begin + no_ack_o <= 1'b0 ; + write_done_o <= 1'b0 ; + + if (stop_sent) + begin + send_stop <= 1'b0 ; + rw_seq_state <= rw_seq_idle ; + end + end + end + + rw_seq_rx_byte: + begin + if (rec_bit) + begin + if (bit_rec) + begin + bits_transfered <= bits_transfered + 1'b1 ; + dat_o <= {dat_o[6:0], sda_i_reg} ; + end + + if (bits_transfered == 'h8) + begin + rec_bit <= 1'b0 ; + dat_rdy_o <= 1'b1 ; + if (doing_read) + send_nack <= 1'b1 ; + else + send_ack <= 1'b1 ; + end + end + else if (send_nack) + begin + dat_rdy_o <= 1'b0 ; + bits_transfered <= 'h0 ; + + if (nack_sent) + begin + send_stop <= 1'b1 ; + send_nack <= 1'b0 ; + end + end + else if (send_ack) + begin + dat_rdy_o <= 1'b0 ; + bits_transfered <= 'h0 ; + + if (~do_seq_read_i) + begin + send_ack <= 1'b0 ; + send_nack <= 1'b1 ; + end + else if (ack_sent) + begin + send_ack <= 1'b0 ; + rec_bit <= 1'b1 ; + end + end + else if (send_stop) + begin + if (stop_sent) + begin + send_stop <= 1'b0 ; + rw_seq_state <= rw_seq_idle ; + end + end + end + endcase + end +end + +endmodule // pci_spoci_ctrl \ No newline at end of file diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v new file mode 100644 index 000000000..e3f1059f4 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v @@ -0,0 +1,167 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "sync_module.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_sync_module.v,v $ +// Revision 1.3 2003/08/14 13:06:03 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// Revision 1.2 2003/03/26 13:16:18 mihad +// Added the reset value parameter to the synchronizer flop module. +// Added resets to all synchronizer flop instances. +// Repaired initial sync value in fifos. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_sync_module +( + set_clk_in, + delete_clk_in, + reset_in, + delete_set_out, + block_set_out, + delete_in +); + +// system inputs from two clock domains +input set_clk_in; +input delete_clk_in; +input reset_in; +// control outputs +output delete_set_out; +output block_set_out; +// control input +input delete_in; + +// internal signals +reg del_bit; +wire meta_del_bit; +reg sync_del_bit; +reg delayed_del_bit; +wire meta_bckp_bit; +reg sync_bckp_bit; +reg delayed_bckp_bit; + + +// DELETE_IN input FF - when set must be active, until it is sinchronously cleared +always@(posedge delete_clk_in or posedge reset_in) +begin + if (reset_in) + del_bit <= 1'b0; + else + begin + if (!delayed_bckp_bit && sync_bckp_bit) + del_bit <= 1'b0; + else if (delete_in) + del_bit <= 1'b1; + end +end +assign block_set_out = del_bit; + +// interemediate stage to clk synchronization flip - flops - this ones are prone to metastability +pci_synchronizer_flop #(1, 0) delete_sync +( + .data_in (del_bit), + .clk_out (set_clk_in), + .sync_data_out (meta_del_bit), + .async_reset (reset_in) +) ; + +// Final synchronization of del_bit signal to the set clock domain +always@(posedge set_clk_in or posedge reset_in) +begin + if (reset_in) + sync_del_bit <= 1'b0; + else + sync_del_bit <= meta_del_bit; +end + +// Delayed sync_del_bit signal for one clock period pulse generation +always@(posedge set_clk_in or posedge reset_in) +begin + if (reset_in) + delayed_del_bit <= 1'b0; + else + delayed_del_bit <= sync_del_bit; +end + +assign delete_set_out = !delayed_del_bit && sync_del_bit; + +// interemediate stage to clk synchronization flip - flops - this ones are prone to metastability +pci_synchronizer_flop #(1, 0) clear_delete_sync +( + .data_in (sync_del_bit), + .clk_out (delete_clk_in), + .sync_data_out (meta_bckp_bit), + .async_reset (reset_in) +) ; + +// Final synchronization of sync_del_bit signal to the delete clock domain +always@(posedge delete_clk_in or posedge reset_in) +begin + if (reset_in) + sync_bckp_bit <= 1'b0; + else + sync_bckp_bit <= meta_bckp_bit; +end + +// Delayed sync_bckp_bit signal for one clock period pulse generation +always@(posedge delete_clk_in or posedge reset_in) +begin + if (reset_in) + delayed_bckp_bit <= 1'b0; + else + delayed_bckp_bit <= sync_bckp_bit; +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v new file mode 100644 index 000000000..b1a05e06c --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v @@ -0,0 +1,103 @@ +//=========================================================================== +// $Id: pci_synchronizer_flop.v,v 1.1 2003/08/14 13:08:58 simons Exp $ +// +////////////////////////////////////////////////////////////////////// +//// //// +//// pci_synchronizer_flop //// +//// //// +//// This file is part of the general opencores effort. //// +//// //// +//// //// +//// Module Description: //// +//// //// +//// Make a rising-edge triggered flop with async reset with a //// +//// distinguished name so that it can be replaced with a flop //// +//// which does not make X's during simulation. //// +//// //// +//// This flop should be used instead of a regular flop for ALL //// +//// cross-clock-domain flops. Manually instantiating this //// +//// flop for all signals which must NEVER go to 1'bX during //// +//// simulation will make it possible for the user to //// +//// substitute a simulation model which does NOT have setup //// +//// and hold checks. //// +//// //// +//// If a target device library has a component which is //// +//// especially well suited to perform this function, it should //// +//// be instantiated by name in this file. Otherwise, the //// +//// behaviorial version of this module will be used. //// +//// //// +//// To Do: //// +//// Nothing //// +//// //// +//// Author(s): //// +//// - anynomous //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_synchronizer_flop.v,v $ +// Revision 1.1 2003/08/14 13:08:58 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +// If the vendor has a flop which is particularly good at settling out of +// metastability, it should be used here. +module pci_synchronizer_flop ( + data_in, clk_out, sync_data_out, async_reset +); +parameter width = 1 ; +parameter reset_val = 0 ; + + input [width-1:0] data_in; + input clk_out; + output [width-1:0] sync_data_out; + input async_reset; + + reg [width-1:0] sync_data_out; + + always @(posedge clk_out or posedge async_reset) + begin + if (async_reset == 1'b1) + begin + sync_data_out <= reset_val; + end + else + begin +// In gate-level simulation, must only go to 1'bX if the input is 1'bX or 1'bZ. +// This should NEVER go to 1'bX due to setup or hold violations. + sync_data_out <= data_in; + end + end +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v new file mode 100644 index 000000000..eabcf7811 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v @@ -0,0 +1,104 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_clk_en.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_clk_en.v,v $ +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_clk_en +( + addr_phase, + config_access, + addr_claim_in, + pci_frame_in, + state_wait, + state_transfere, + state_default, + clk_enable +); + +input addr_phase ; // indicates registered address phase on PCI bus +input config_access ; // indicates configuration access +input addr_claim_in ; // indicates claimed input PCI address +input pci_frame_in ; // critical constrained input signal +input state_wait ; // indicates WAIT state of FSM +input state_transfere ; // indicates TRANSFERE state of FSM +input state_default ; // indicates DEFAULT state of FSM + +output clk_enable ; // FSM clock enable output + + +// clock enable signal when FSM is in IDLE state +wire s_idle_clk_en = ((addr_phase && config_access) || + (addr_phase && ~config_access && addr_claim_in)) ; + +// clock enable signal when FSM is in WAIT state or in DEFAULT state +wire s_wait_clk_en = (state_wait || state_default) ; + +// clock enable signal when FSM is in TRANSFERE state +wire s_tran_clk_en = (state_transfere && pci_frame_in) ; + + +// Clock enable signal for FSM with preserved hierarchy for minimum delay! +assign clk_enable = (s_idle_clk_en || s_wait_clk_en || s_tran_clk_en) ; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v new file mode 100644 index 000000000..c2d18fb7e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_devs_crit.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_devs_crit.v,v $ +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_devs_crit +( + devs_w, + devs_w_frm, + devs_w_frm_irdy, + pci_frame_in, + pci_irdy_in, + pci_devsel_out +); + +input devs_w ; // devsel signal (composed without critical signals) that do not need critical inputs +input devs_w_frm ; // devsel signal (composed without critical signals) that needs AND with critical FRAME input +input devs_w_frm_irdy ; // devsel signal (composed without critical signals) that needs AND with critical FRAME and + // IRDY inputs +input pci_frame_in ; // critical constrained input signal +input pci_irdy_in ; // critical constrained input signal + +output pci_devsel_out ; // PCI devsel output + +// PCI devsel output with preserved hierarchy for minimum delay! +assign pci_devsel_out = ~(devs_w || (devs_w_frm && ~pci_frame_in) || (devs_w_frm_irdy && ~pci_frame_in && pci_irdy_in)) ; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v new file mode 100644 index 000000000..a3ddbe1a3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v @@ -0,0 +1,962 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_interface.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_interface.v,v $ +// Revision 1.11 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.10 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.9 2003/08/21 20:55:14 tadejm +// Corrected bug when writing to FIFO (now it is registered). +// +// Revision 1.8 2003/08/08 16:36:33 tadejm +// Added 'three_left_out' to pci_pciw_fifo signaling three locations before full. Added comparison between current registered cbe and next unregistered cbe to signal wb_master whether it is allowed to performe burst or not. Due to this, I needed 'three_left_out' so that writing to pci_pciw_fifo can be registered, otherwise timing problems would occure. +// +// Revision 1.7 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.6 2003/01/21 16:06:56 mihad +// Bug fixes, testcases added. +// +// Revision 1.5 2002/08/22 13:28:04 mihad +// Updated for synthesis purposes. Gate level simulation was failing in some configurations +// +// Revision 1.4 2002/02/19 16:32:37 mihad +// Modified testbench and fixed some bugs +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +`include "bus_commands.v" +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_interface +( + // system inputs + clk_in, + reset_in, + + // PCI Target side of INTERFACE + address_in, + addr_claim_out, + bc_in, + bc0_in, + data_in, + data_out, + be_in, + next_be_in, + req_in, + rdy_in, + addr_phase_in, + bckp_devsel_in, + bckp_trdy_in, + bckp_stop_in, + last_reg_in, + frame_reg_in, + fetch_pcir_fifo_in, + load_medium_reg_in, + sel_fifo_mreg_in, + sel_conf_fifo_in, + load_to_pciw_fifo_in, + load_to_conf_in, + same_read_out, + + norm_access_to_config_out, + read_completed_out, + read_processing_out, + target_abort_out, + disconect_wo_data_out, + disconect_w_data_out, + pciw_fifo_full_out, + pcir_fifo_data_err_out, + wbw_fifo_empty_out, + wbu_del_read_comp_pending_out, + + // Delayed synchronizacion module signals + req_out, + done_out, + in_progress_out, + req_req_pending_in, + req_comp_pending_in, + addr_out, + be_out, + we_out, + bc_out, + burst_ok_out, + strd_addr_in, + strd_bc_in, + status_in, + comp_flush_in, + + // FIFO signals + pcir_fifo_renable_out, + pcir_fifo_data_in, + pcir_fifo_be_in, + pcir_fifo_control_in, + pcir_fifo_flush_out, + pcir_fifo_almost_empty_in, + pcir_fifo_empty_in, + pciw_fifo_wenable_out, + pciw_fifo_addr_data_out, + pciw_fifo_cbe_out, + pciw_fifo_control_out, + pciw_fifo_three_left_in, + pciw_fifo_two_left_in, + pciw_fifo_almost_full_in, + pciw_fifo_full_in, + wbw_fifo_empty_in, + wbu_del_read_comp_pending_in, + + // Configuration space signals + conf_addr_out, + conf_data_out, + conf_data_in, + conf_be_out, + conf_we_out, + conf_re_out, + mem_enable_in, + io_enable_in, + mem_io_addr_space0_in, + mem_io_addr_space1_in, + mem_io_addr_space2_in, + mem_io_addr_space3_in, + mem_io_addr_space4_in, + mem_io_addr_space5_in, + pre_fetch_en0_in, + pre_fetch_en1_in, + pre_fetch_en2_in, + pre_fetch_en3_in, + pre_fetch_en4_in, + pre_fetch_en5_in, + pci_base_addr0_in, + pci_base_addr1_in, + pci_base_addr2_in, + pci_base_addr3_in, + pci_base_addr4_in, + pci_base_addr5_in, + pci_addr_mask0_in, + pci_addr_mask1_in, + pci_addr_mask2_in, + pci_addr_mask3_in, + pci_addr_mask4_in, + pci_addr_mask5_in, + pci_tran_addr0_in, + pci_tran_addr1_in, + pci_tran_addr2_in, + pci_tran_addr3_in, + pci_tran_addr4_in, + pci_tran_addr5_in, + addr_tran_en0_in, + addr_tran_en1_in, + addr_tran_en2_in, + addr_tran_en3_in, + addr_tran_en4_in, + addr_tran_en5_in +) ; + +`ifdef HOST + `ifdef NO_CNF_IMAGE + parameter pci_ba0_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + `else + parameter pci_ba0_width = 20 ; + `endif +`endif + +`ifdef GUEST + parameter pci_ba0_width = 20 ; +`endif + +parameter pci_ba1_5_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + +/*================================================================================================================== +System inputs. +==================================================================================================================*/ +// PCI side clock and reset +input clk_in, + reset_in ; + + +/*================================================================================================================== +Side of the PCI Target state machine +==================================================================================================================*/ +// Data, byte enables, bus commands and address ports +input [31:0] address_in ; // current request address input - registered +output addr_claim_out ; // current request address claim output +input [3:0] bc_in ; // current request bus command input - registered +input bc0_in ; // current cycle RW signal +output [31:0] data_out ; // for read operations - current dataphase data output +input [31:0] data_in ; // for write operations - current request data input - registered +input [3:0] be_in ; // current dataphase byte enable inputs - registered +input [3:0] next_be_in ; // next dataphase byte enable inputs - NOT registered +// Port connection control signals from PCI FSM +input req_in ; // Read is requested to WB master from PCI side +input rdy_in ; // DATA / ADDRESS selection from PCI side when read or write - registered +input addr_phase_in ; // Indicates address phase and also fast-back-to-back address phase - registered +input bckp_devsel_in ; // DEVSEL input (which is registered) equivalent +input bckp_trdy_in ; // TRDY input (which is registered) equivalent +input bckp_stop_in ; // STOP input (which is registered) equivalent +input last_reg_in ; // Indicates last data phase - registered +input frame_reg_in ; // FRAME input signal - registered +input fetch_pcir_fifo_in ;// Read enable for PCIR_FIFO when when read is finishen on WB side +input load_medium_reg_in ;// Load data from PCIR_FIFO to medium register (first data must be prepared on time) +input sel_fifo_mreg_in ; // Read data selection between PCIR_FIFO and medium register +input sel_conf_fifo_in ; // Read data selection between Configuration registers and "FIFO" +input load_to_pciw_fifo_in ;// Write enable to PCIW_FIFO +input load_to_conf_in ; // Write enable to Configuration space registers + + +/*================================================================================================================== +Status outputs to PCI side (FSM) +==================================================================================================================*/ +output same_read_out ; // Indicates the same read request (important when read is finished on WB side) +output norm_access_to_config_out ; // Indicates the access to Configuration space with MEMORY commands +output read_completed_out ; // Indicates that read request is completed on WB side +output read_processing_out ; // Indicates that read request is processing on WB side +output target_abort_out ; // Indicates target abort termination +output disconect_wo_data_out ; // Indicates disconnect without data termination +output disconect_w_data_out ; // Indicates disconnect with data termination +output pciw_fifo_full_out ; // Indicates that write PCIW_FIFO is full +output pcir_fifo_data_err_out ; // Indicates data error on current data read from PCIR_FIFO +output wbw_fifo_empty_out ; // Indicates that WB SLAVE has no data to be written to PCI bus +output wbu_del_read_comp_pending_out ; // Indicates that WB Unit has a delayed read poending! + +/*================================================================================================================== +Read request interface through Delayed sinchronization module to WB Master +==================================================================================================================*/ +// request, completion, done and progress indicator outputs for delayed_sync module where they are synchronized +output req_out, // request qualifier - when 1 it indicates that valid data is provided on outputs + done_out, // done output - when 1 indicates that PCI Target has completed a cycle on its bus + in_progress_out ; // out progress indicator - indicates that current completion is in progress on + // PCI Target side +// pending indication inputs - PCI Target side must know about requests and completions +input req_req_pending_in ; // request pending input for PCI Target side +input req_comp_pending_in ; // completion pending input for PCI Target side - it indicates when completion + // is ready for completing on PCI Target bus +// various data outputs - PCI Target sets address, bus command, byte enables, write enable and burst +output [31:0] addr_out ; // address bus output +output [3:0] be_out ; // byte enable output +output we_out ; // write enable output - read/write request indication 1 = write request / 0 = read request +output [3:0] bc_out ; // bus command output +output burst_ok_out ; // pre-fetch enable & burst read - qualifies pre-fetch for access to current image space + +// completion side signals encoded termination status - 0 = normal completion / 1 = error terminated completion +input [31:0] strd_addr_in ; // Stored requested read access address +input [3:0] strd_bc_in ; // Stored requested read access bus command +input status_in ; // Error status reported - NOT USED because FIFO control bits determin data error status +input comp_flush_in ; // If completition counter (2^16 clk periods) has expired, PCIR_FIFO must flush data + + +/*================================================================================================================== +PCIR_PCIW_FIFO signals from pci side +==================================================================================================================*/ +// PCIR_FIFO control signals used for fetching data from PCIR_FIFO +output pcir_fifo_renable_out ; // read enable output to PCIR_FIFO +input [31:0] pcir_fifo_data_in ; // data input from PCIR_FIFO +input [3:0] pcir_fifo_be_in ; // byte enable input from PCIR_FIFO +input [3:0] pcir_fifo_control_in ; // control signals input from PCIR_FIFO +output pcir_fifo_flush_out ; // flush PCIR_FIFO +input pcir_fifo_almost_empty_in ; // almost empty indicator from PCIR_FIFO +input pcir_fifo_empty_in ; // empty indicator + +// PCIW_FIFO control signals used for sinking data into PCIW_FIFO and status monitoring +output pciw_fifo_wenable_out ; // write enable output to PCIW_FIFO +wire pciw_fifo_wenable ; // not registered we +output [31:0] pciw_fifo_addr_data_out ; // address / data output signals to PCIW_FIFO +output [3:0] pciw_fifo_cbe_out ; // command / byte enable signals to PCIW_FIFO +output [3:0] pciw_fifo_control_out ; // control signals to PCIW_FIFO +input pciw_fifo_three_left_in ; // three data spaces left in PCIW_FIFO +input pciw_fifo_two_left_in ; // two data spaces left in PCIW_FIFO +input pciw_fifo_almost_full_in ; // almost full indicator from PCIW_FIFO +input pciw_fifo_full_in ; // full indicator from PCIW_FIFO + +// WBW_FIFO empy control signal used when delayed read is complete in PCIR_FIFO +input wbw_fifo_empty_in ; // empty indicator from WBW_FIFO +input wbu_del_read_comp_pending_in ; // delayed read pending indicator from WB Unit + + +/*================================================================================================================== +Configuration space signals - from and to registers +==================================================================================================================*/ +// BUS for reading and writing to configuration space registers +output [11:0] conf_addr_out ; // address to configuration space when there is access to it +output [31:0] conf_data_out ; // data to configuration space - for writing to registers +input [31:0] conf_data_in ; // data from configuration space - for reading from registers +output [3:0] conf_be_out ; // byte enables used for correct writing to configuration space +output conf_we_out ; // write enable control signal - 1 for writing / 0 for nothing +output conf_re_out ; // read enable control signal - 1 for reading / 0 for nothing + +// Inputs for image control registers +input mem_enable_in ; // allowed access to memory mapped image +input io_enable_in ; // allowed access to io mapped image + +// Inputs needed for determining if image is assigned to memory or io space with pre-fetch and address translation +input mem_io_addr_space0_in ; // bit-0 in pci_base_addr0 register +input mem_io_addr_space1_in ; // bit-0 in pci_base_addr1 register +input mem_io_addr_space2_in ; // bit-0 in pci_base_addr2 register +input mem_io_addr_space3_in ; // bit-0 in pci_base_addr3 register +input mem_io_addr_space4_in ; // bit-0 in pci_base_addr4 register +input mem_io_addr_space5_in ; // bit-0 in pci_base_addr5 register +input pre_fetch_en0_in ; // bit-1 in pci_image_ctr0 register +input pre_fetch_en1_in ; // bit-1 in pci_image_ctr1 register +input pre_fetch_en2_in ; // bit-1 in pci_image_ctr2 register +input pre_fetch_en3_in ; // bit-1 in pci_image_ctr3 register +input pre_fetch_en4_in ; // bit-1 in pci_image_ctr4 register +input pre_fetch_en5_in ; // bit-1 in pci_image_ctr5 register + +// Input from image registers - register values needed for decoder to work properly +input [pci_ba0_width - 1:0] pci_base_addr0_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_base_addr1_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_base_addr2_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_base_addr3_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_base_addr4_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_base_addr5_in ; // base address from base address register +input [pci_ba1_5_width - 1:0] pci_addr_mask0_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_addr_mask1_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_addr_mask2_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_addr_mask3_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_addr_mask4_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_addr_mask5_in ; // masking of base address from address mask register +input [pci_ba1_5_width - 1:0] pci_tran_addr0_in ; // translation address from address translation register +input [pci_ba1_5_width - 1:0] pci_tran_addr1_in ; // translation address from address translation register +input [pci_ba1_5_width - 1:0] pci_tran_addr2_in ; // translation address from address translation register +input [pci_ba1_5_width - 1:0] pci_tran_addr3_in ; // translation address from address translation register +input [pci_ba1_5_width - 1:0] pci_tran_addr4_in ; // translation address from address translation register +input [pci_ba1_5_width - 1:0] pci_tran_addr5_in ; // translation address from address translation register + +input addr_tran_en0_in ; // address translation enable bit +input addr_tran_en1_in ; // address translation enable bit +input addr_tran_en2_in ; // address translation enable bit +input addr_tran_en3_in ; // address translation enable bit +input addr_tran_en4_in ; // address translation enable bit +input addr_tran_en5_in ; // address translation enable bit + +/*================================================================================================================== +END of input / output PORT DEFINITONS !!! +==================================================================================================================*/ + +// address output from address multiplexer +reg [31:0] address ; +// prefetch enable for access to selected image space +reg pre_fetch_en ; + +// Input addresses and image hits from address decoders - addresses are multiplexed to address +`ifdef HOST + `ifdef NO_CNF_IMAGE + `ifdef PCI_IMAGE0 // if PCI bridge is HOST and IMAGE0 is assigned as general image space +wire hit0_in ; +wire [31:0] address0_in ; +wire pre_fetch_en0 = pre_fetch_en0_in ; + `else +wire hit0_in = 1'b0 ; +wire [31:0] address0_in = 32'h0 ; +wire pre_fetch_en0 = 1'b0 ; + `endif + `else +wire hit0_in ; +wire [31:0] address0_in ; +wire pre_fetch_en0 = pre_fetch_en0_in ; + `endif +`else // GUEST +wire hit0_in ; +wire [31:0] address0_in ; +wire pre_fetch_en0 = pre_fetch_en0_in ; +`endif + +wire hit1_in ; +wire [31:0] address1_in ; +wire pre_fetch_en1 = pre_fetch_en1_in ; + +`ifdef PCI_IMAGE2 +wire hit2_in ; +wire [31:0] address2_in ; +wire pre_fetch_en2 = pre_fetch_en2_in ; +`else +wire hit2_in = 1'b0 ; +wire [31:0] address2_in = 32'h0 ; +wire pre_fetch_en2 = 1'b0 ; +`endif + +`ifdef PCI_IMAGE3 +wire hit3_in ; +wire [31:0] address3_in ; +wire pre_fetch_en3 = pre_fetch_en3_in ; +`else +wire hit3_in = 1'b0 ; +wire [31:0] address3_in = 32'h0 ; +wire pre_fetch_en3 = 1'b0 ; +`endif + +`ifdef PCI_IMAGE4 +wire hit4_in ; +wire [31:0] address4_in ; +wire pre_fetch_en4 = pre_fetch_en4_in ; +`else +wire hit4_in = 1'b0 ; +wire [31:0] address4_in = 32'h0 ; +wire pre_fetch_en4 = 1'b0 ; +`endif + +`ifdef PCI_IMAGE5 +wire hit5_in ; +wire [31:0] address5_in ; +wire pre_fetch_en5 = pre_fetch_en5_in ; +`else +wire hit5_in = 1'b0 ; +wire [31:0] address5_in = 32'h0 ; +wire pre_fetch_en5 = 1'b0 ; +`endif + +// Include address decoders +`ifdef HOST + `ifdef NO_CNF_IMAGE + `ifdef PCI_IMAGE0 // if PCI bridge is HOST and IMAGE0 is assigned as general image space + pci_pci_decoder #(pci_ba0_width) decoder0 + (.hit (hit0_in), + .addr_out (address0_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr0_in), + .mask_addr (pci_addr_mask0_in), + .tran_addr (pci_tran_addr0_in), + .at_en (addr_tran_en0_in), + .mem_io_space (mem_io_addr_space0_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; + `endif + `else + pci_pci_decoder #(pci_ba0_width) decoder0 + (.hit (hit0_in), + .addr_out (address0_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr0_in), + .mask_addr ({pci_ba0_width{1'b1}}), + .tran_addr ({pci_ba0_width{1'b0}}), + .at_en (1'b0), + .mem_io_space (1'b0), + .mem_en (mem_enable_in), + .io_en (1'b0) + ) ; + `endif +`else // GUEST + pci_pci_decoder #(pci_ba0_width) decoder0 + (.hit (hit0_in), + .addr_out (address0_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr0_in), + .mask_addr ({pci_ba0_width{1'b1}}), + .tran_addr ({pci_ba0_width{1'b0}}), + .at_en (1'b0), + .mem_io_space (1'b0), + .mem_en (mem_enable_in), + .io_en (1'b0) + ) ; +`endif + pci_pci_decoder #(`PCI_NUM_OF_DEC_ADDR_LINES) decoder1 + (.hit (hit1_in), + .addr_out (address1_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr1_in), + .mask_addr (pci_addr_mask1_in), + .tran_addr (pci_tran_addr1_in), + .at_en (addr_tran_en1_in), + .mem_io_space (mem_io_addr_space1_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; +`ifdef PCI_IMAGE2 + pci_pci_decoder #(`PCI_NUM_OF_DEC_ADDR_LINES) decoder2 + (.hit (hit2_in), + .addr_out (address2_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr2_in), + .mask_addr (pci_addr_mask2_in), + .tran_addr (pci_tran_addr2_in), + .at_en (addr_tran_en2_in), + .mem_io_space (mem_io_addr_space2_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; +`endif +`ifdef PCI_IMAGE3 + pci_pci_decoder #(`PCI_NUM_OF_DEC_ADDR_LINES) decoder3 + (.hit (hit3_in), + .addr_out (address3_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr3_in), + .mask_addr (pci_addr_mask3_in), + .tran_addr (pci_tran_addr3_in), + .at_en (addr_tran_en3_in), + .mem_io_space (mem_io_addr_space3_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; +`endif +`ifdef PCI_IMAGE4 + pci_pci_decoder #(`PCI_NUM_OF_DEC_ADDR_LINES) decoder4 + (.hit (hit4_in), + .addr_out (address4_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr4_in), + .mask_addr (pci_addr_mask4_in), + .tran_addr (pci_tran_addr4_in), + .at_en (addr_tran_en4_in), + .mem_io_space (mem_io_addr_space4_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; +`endif +`ifdef PCI_IMAGE5 + pci_pci_decoder #(`PCI_NUM_OF_DEC_ADDR_LINES) decoder5 + (.hit (hit5_in), + .addr_out (address5_in), + .addr_in (address_in), + .bc_in (bc_in), + .base_addr (pci_base_addr5_in), + .mask_addr (pci_addr_mask5_in), + .tran_addr (pci_tran_addr5_in), + .at_en (addr_tran_en5_in), + .mem_io_space (mem_io_addr_space5_in), + .mem_en (mem_enable_in), + .io_en (io_enable_in) + ) ; +`endif + +// Internal signals for image hit determination +reg addr_claim ;// address claim signal is asinchronous set for addr_claim_out signal to PCI Target SM + +// Determining if image 0 is assigned to configuration space or as normal pci to wb access! +// if normal access is allowed to configuration space, then hit0 is hit0_conf +`ifdef HOST + `ifdef NO_CNF_IMAGE + parameter hit0_conf = 1'b0 ; + `else + parameter hit0_conf = 1'b1 ; // if normal access is allowed to configuration space, then hit0 is hit0_conf + `endif +`else // GUEST + parameter hit0_conf = 1'b1 ; // if normal access is allowed to configuration space, then hit0 is hit0_conf +`endif + +// Logic with address mux, determining if address is still in the same image space and if it is prefetced or not +always@(hit5_in or hit4_in or hit3_in or hit2_in or hit1_in or hit0_in or + address5_in or address4_in or address3_in or address2_in or address1_in or address0_in or + pre_fetch_en5 or + pre_fetch_en4 or + pre_fetch_en3 or + pre_fetch_en2 or + pre_fetch_en1 or + pre_fetch_en0 + ) +begin + addr_claim <= (hit5_in || hit4_in) || (hit3_in || hit2_in || hit1_in || hit0_in) ; + case ({hit5_in, hit4_in, hit3_in, hit2_in, hit0_in}) + 5'b10000 : + begin + address <= address5_in ; + pre_fetch_en <= pre_fetch_en5 ; + end + 5'b01000 : + begin + address <= address4_in ; + pre_fetch_en <= pre_fetch_en4 ; + end + 5'b00100 : + begin + address <= address3_in ; + pre_fetch_en <= pre_fetch_en3 ; + end + 5'b00010 : + begin + address <= address2_in ; + pre_fetch_en <= pre_fetch_en2 ; + end + 5'b00001 : + begin + address <= address0_in ; + pre_fetch_en <= pre_fetch_en0 ; + end + default : // IMAGE 1 is always included into PCI bridge + begin + address <= address1_in ; + pre_fetch_en <= pre_fetch_en1 ; + end + endcase +end + +// Address claim output to PCI Target SM +assign addr_claim_out = addr_claim ; + +reg [31:0] norm_address ; // stored normal address (decoded and translated) for access to WB +reg norm_prf_en ; // stored pre-fetch enable +reg [3:0] norm_bc ; // stored bus-command +reg same_read_reg ; // stored SAME_READ information +reg target_rd ; // delayed registered TRDY output equivalent signal + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + norm_address <= #`FF_DELAY 32'h0000_0000 ; + norm_prf_en <= #`FF_DELAY 1'b0 ; + norm_bc <= #`FF_DELAY 4'h0 ; + same_read_reg <= #`FF_DELAY 1'b0 ; + end + else + begin + if (addr_phase_in) + begin + norm_address <= #`FF_DELAY address ; + norm_prf_en <= #`FF_DELAY pre_fetch_en ; + norm_bc <= #`FF_DELAY bc_in ; + same_read_reg <= #`FF_DELAY same_read_out ; + end + end +end + +`ifdef HOST + `ifdef NO_CNF_IMAGE + reg [1:0] strd_address ; // stored INPUT address for accessing Configuration space registers + `else + reg [11:0] strd_address ; // stored INPUT address for accessing Configuration space registers + `endif +`else + reg [11:0] strd_address ; // stored INPUT address for accessing Configuration space registers +`endif +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + strd_address <= #`FF_DELAY 0 ; + end + else + begin + if (addr_phase_in) + begin +`ifdef HOST + `ifdef NO_CNF_IMAGE + strd_address <= #`FF_DELAY address_in[1:0] ; + `else + strd_address <= #`FF_DELAY address_in[11:0] ; + `endif +`else + strd_address <= #`FF_DELAY address_in[11:0] ; +`endif + end + end +end + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + target_rd <= #`FF_DELAY 1'b0 ; + end + else + begin + if (same_read_reg && !bckp_trdy_in) + target_rd <= #`FF_DELAY 1'b1 ;// Signal indicates when target ready is deaserted on PCI bus + else if (same_read_reg && bckp_devsel_in && !bckp_stop_in) + target_rd <= #`FF_DELAY 1'b1 ;// Signal indicates when target ready is deaserted on PCI bus + else if ((!same_read_reg) || (last_reg_in && target_rd)) + target_rd <= #`FF_DELAY 1'b0 ;// Signal indicates when target ready is deaserted on PCI bus + end +end +// '1' indicates asserted TRDY signal when same read operation is performed +wire target_rd_completed = target_rd ; + +reg same_read_request ; + +// When delayed read is completed on WB, addres and bc must be compered, if there is the same read request +always@(address or strd_addr_in or bc_in or strd_bc_in) +begin + if ((address == strd_addr_in) & (bc_in == strd_bc_in)) + same_read_request <= 1'b1 ; + else + same_read_request <= 1'b0 ; +end + +assign same_read_out = (same_read_request) ; // && ~pcir_fifo_empty_in) ; + +// Signals for byte enable checking +reg addr_burst_ok ; +reg io_be_ok ; + +// Byte enable checking for IO, MEMORY and CONFIGURATION spaces - be_in is active low! +always@(strd_address or be_in) +begin + case (strd_address[1:0]) + 2'b11 : + begin + addr_burst_ok <= 1'b0 ; + io_be_ok <= (be_in[2] && be_in[1] && be_in[0]) ; // only be3 can be active + end + 2'b10 : + begin + addr_burst_ok <= 1'b0 ; + io_be_ok <= (~be_in[2] && be_in[1] && be_in[0]) || (be_in[3] && be_in[2] && be_in[1] && be_in[0]) ; + end + 2'b01 : + begin + addr_burst_ok <= 1'b0 ; + io_be_ok <= (~be_in[1] && be_in[0]) || (be_in[3] && be_in[2] && be_in[1] && be_in[0]) ; + end + default : // 2'b00 + begin + addr_burst_ok <= 1'b1 ; + io_be_ok <= (~be_in[0]) || (be_in[3] && be_in[2] && be_in[1] && be_in[0]) ; + end + endcase +end + +wire calc_target_abort = (norm_bc[3:1] == `BC_IO_RW) ? !io_be_ok : 1'b0 ; + +wire [3:0] pcir_fifo_control_input = pcir_fifo_empty_in ? 4'h0 : pcir_fifo_control_in ; + +// Medium registers for data and control busses from PCIR_FIFO +reg [31:0] pcir_fifo_data_reg ; +reg [3:0] pcir_fifo_ctrl_reg ; + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + pcir_fifo_data_reg <= #`FF_DELAY 32'h0000_0000 ; + pcir_fifo_ctrl_reg <= #`FF_DELAY 4'h0 ; + end + else + begin + if (load_medium_reg_in) + begin + pcir_fifo_data_reg <= #`FF_DELAY pcir_fifo_data_in ; + pcir_fifo_ctrl_reg <= #`FF_DELAY pcir_fifo_control_input ; + end + end +end + +// when disconnect is signalled, the next data written to fifo will be the last +// also when this happens, disconnect must stay asserted until last data is written to the fifo +reg keep_desconnect_wo_data_set ; + +// selecting "fifo data" from medium registers or from PCIR_FIFO +wire [31:0] pcir_fifo_data = (sel_fifo_mreg_in && !pcir_fifo_empty_in) ? pcir_fifo_data_in : pcir_fifo_data_reg ; +wire [3:0] pcir_fifo_ctrl = (sel_fifo_mreg_in && !pcir_fifo_empty_in) ? pcir_fifo_control_input : pcir_fifo_ctrl_reg ; + +// signal assignments to PCI Target FSM +assign read_completed_out = req_comp_pending_in ; // completion pending input for requesting side of the bridge +assign read_processing_out = req_req_pending_in ; // request pending input for requesting side + // when '1', the bus command is IO command - not supported commands are checked in pci_decoder modules + wire io_memory_bus_command = !norm_bc[3] && !norm_bc[2] ; +assign disconect_wo_data_out = ( + ((/*pcir_fifo_ctrl[`LAST_CTRL_BIT] ||*/ pcir_fifo_empty_in || ~burst_ok_out/*addr_burst_ok*/ || io_memory_bus_command) && + ~bc0_in && ~frame_reg_in) || + ((pciw_fifo_full_in || pciw_fifo_almost_full_in || keep_desconnect_wo_data_set || pciw_fifo_two_left_in || + (pciw_fifo_three_left_in && pciw_fifo_wenable) || ~addr_burst_ok || io_memory_bus_command) && + bc0_in && ~frame_reg_in) + ) ; +assign disconect_w_data_out = ( + ( burst_ok_out && !io_memory_bus_command && ~bc0_in ) || + ( addr_burst_ok && !io_memory_bus_command && bc0_in ) + ) ; +assign target_abort_out = ( ~addr_phase_in && calc_target_abort ) ; + +`ifdef HOST + `ifdef NO_CNF_IMAGE + // signal assignments to PCI Target FSM + assign norm_access_to_config_out = 1'b0 ; + // control signal assignments to read request sinchronization module + assign done_out = (target_rd_completed && last_reg_in) ; + assign in_progress_out = (same_read_reg && ~bckp_trdy_in) ; + // signal used for PCIR_FIFO flush (with comp_flush_in signal) + wire pcir_fifo_flush = (target_rd_completed && last_reg_in && ~pcir_fifo_empty_in) ; + `else + // signal assignments to PCI Target FSM + assign norm_access_to_config_out = (hit0_in && hit0_conf) ; + // control signal assignments to read request sinchronization module + assign done_out = (~sel_conf_fifo_in && target_rd_completed && last_reg_in) ; + assign in_progress_out = (~sel_conf_fifo_in && same_read_reg && ~bckp_trdy_in) ; + // signal used for PCIR_FIFO flush (with comp_flush_in signal) + wire pcir_fifo_flush = (~sel_conf_fifo_in && target_rd_completed && last_reg_in && ~pcir_fifo_empty_in) ; + `endif +`else + // signal assignments to PCI Target FSM + assign norm_access_to_config_out = (hit0_in && hit0_conf) ; + // control signal assignments to read request sinchronization module + assign done_out = (~sel_conf_fifo_in && target_rd_completed && last_reg_in) ; + assign in_progress_out = (~sel_conf_fifo_in && same_read_reg && ~bckp_trdy_in) ; + // signal used for PCIR_FIFO flush (with comp_flush_in signal) + wire pcir_fifo_flush = (~sel_conf_fifo_in && target_rd_completed && last_reg_in && ~pcir_fifo_empty_in) ; +`endif + +// flush signal for PCIR_FIFO must be registered, since it asinchronously resets some status registers +wire pcir_fifo_flush_reg ; +pci_async_reset_flop async_reset_as_pcir_flush +( + .data_in (comp_flush_in || pcir_fifo_flush), + .clk_in (clk_in), + .async_reset_data_out (pcir_fifo_flush_reg), + .reset_in (reset_in) +) ; + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + keep_desconnect_wo_data_set <= #1 1'b0 ; + else if (keep_desconnect_wo_data_set && pciw_fifo_wenable) + keep_desconnect_wo_data_set <= #1 1'b0 ; + else if (pciw_fifo_wenable && disconect_wo_data_out) + keep_desconnect_wo_data_set <= #1 1'b1 ; +end + + +// signal assignments from fifo to PCI Target FSM +assign wbw_fifo_empty_out = wbw_fifo_empty_in ; +assign wbu_del_read_comp_pending_out = wbu_del_read_comp_pending_in ; +assign pciw_fifo_full_out = (pciw_fifo_full_in || pciw_fifo_almost_full_in || pciw_fifo_two_left_in || pciw_fifo_three_left_in) ; +assign pcir_fifo_data_err_out = pcir_fifo_ctrl[`DATA_ERROR_CTRL_BIT] && !sel_conf_fifo_in ; +// signal assignments to PCIR FIFO fifo +assign pcir_fifo_flush_out = pcir_fifo_flush_reg ; +assign pcir_fifo_renable_out = fetch_pcir_fifo_in && !pcir_fifo_empty_in ; + +// signal assignments to PCIW FIFO +reg pciw_fifo_wenable_out; +assign pciw_fifo_wenable = load_to_pciw_fifo_in ; +reg [3:0] pciw_fifo_control_out; +reg [31:0] pciw_fifo_addr_data_out; +reg [3:0] pciw_fifo_cbe_out; +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + pciw_fifo_wenable_out <= #1 1'b0; + pciw_fifo_control_out <= #1 4'h0; + // data and address outputs assignments to PCIW_FIFO - correction of 2 LSBits + pciw_fifo_addr_data_out <= #1 32'h0; + pciw_fifo_cbe_out <= #1 4'h0; + end + else + begin + pciw_fifo_wenable_out <= #1 load_to_pciw_fifo_in ; + pciw_fifo_control_out[`ADDR_CTRL_BIT] <= #1 ~rdy_in ; + pciw_fifo_control_out[`BURST_BIT] <= #1 rdy_in ? ~frame_reg_in : 1'b0 ; + // if '1' then next burst BE is not equat to current one => burst will be chopped into single transfers + pciw_fifo_control_out[`DATA_ERROR_CTRL_BIT] <= #1 rdy_in && (next_be_in != be_in) && ~bckp_trdy_in; // valid comp. + pciw_fifo_control_out[`LAST_CTRL_BIT] <= #1 rdy_in && (frame_reg_in || (bckp_trdy_in && ~bckp_stop_in)); + // data and address outputs assignments to PCIW_FIFO - correction of 2 LSBits + pciw_fifo_addr_data_out <= #1 rdy_in ? data_in : {norm_address[31:2], + norm_address[1] && io_memory_bus_command, + norm_address[0] && io_memory_bus_command} ; + pciw_fifo_cbe_out <= #1 rdy_in ? be_in : norm_bc ; + end +end + +`ifdef HOST + `ifdef NO_CNF_IMAGE + // data and address outputs assignments to PCI Target FSM + assign data_out = pcir_fifo_data ; + `else + // data and address outputs assignments to PCI Target FSM + assign data_out = sel_conf_fifo_in ? conf_data_in : pcir_fifo_data ; + `endif +`else + // data and address outputs assignments to PCI Target FSM + assign data_out = sel_conf_fifo_in ? conf_data_in : pcir_fifo_data ; +`endif + +// data and address outputs assignments to read request sinchronization module +assign req_out = req_in ; + // this address is stored in delayed_sync module and is connected back as strd_addr_in +assign addr_out = norm_address[31:0] ; // correction of 2 LSBits is done in wb_master module, original address must be saved +assign be_out = be_in ; +assign we_out = 1'b0 ; +assign bc_out = norm_bc ; +// burst is OK for reads when there is ((MEM_READ_LN or MEM_READ_MUL) and AD[1:0]==2'b00) OR +// (MEM_READ and Prefetchable_IMAGE and AD[1:0]==2'b00) +assign burst_ok_out = (norm_bc[3] && addr_burst_ok) || (norm_bc[2] && norm_prf_en && addr_burst_ok) ; +// data and address outputs assignments to Configuration space +`ifdef HOST + `ifdef NO_CNF_IMAGE + assign conf_data_out = 32'h0 ; + assign conf_addr_out = 12'h0 ; + assign conf_be_out = 4'b0 ; + assign conf_we_out = 1'h0 ; + `else + assign conf_data_out = data_in ; + assign conf_addr_out = strd_address[11:0] ; + assign conf_be_out = be_in ; + assign conf_we_out = load_to_conf_in ; + `endif +`else + assign conf_data_out = data_in ; + assign conf_addr_out = strd_address[11:0] ; + assign conf_be_out = be_in ; + assign conf_we_out = load_to_conf_in ; +`endif +// NOT USED NOW, SONCE READ IS ASYNCHRONOUS +//assign conf_re_out = fetch_conf_in ; +assign conf_re_out = 1'b0 ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v new file mode 100644 index 000000000..5d7746bbb --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v @@ -0,0 +1,758 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_sm.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_sm.v,v $ +// Revision 1.11 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.10 2003/08/08 16:36:33 tadejm +// Added 'three_left_out' to pci_pciw_fifo signaling three locations before full. Added comparison between current registered cbe and next unregistered cbe to signal wb_master whether it is allowed to performe burst or not. Due to this, I needed 'three_left_out' so that writing to pci_pciw_fifo can be registered, otherwise timing problems would occure. +// +// Revision 1.9 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.8 2003/01/21 16:06:56 mihad +// Bug fixes, testcases added. +// +// Revision 1.7 2002/09/24 19:09:17 mihad +// Number of state bits define was removed +// +// Revision 1.6 2002/09/24 18:30:00 mihad +// Changed state machine encoding to true one-hot +// +// Revision 1.5 2002/08/22 09:07:06 mihad +// Fixed a bug and provided testcase for it. Target was responding to configuration cycle type 1 transactions. +// +// Revision 1.4 2002/02/19 16:32:37 mihad +// Modified testbench and fixed some bugs +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_sm +( + // system inputs + clk_in, + reset_in, + // master inputs + pci_frame_in, + pci_irdy_in, + pci_idsel_in, + pci_frame_reg_in, + pci_irdy_reg_in, + pci_idsel_reg_in, + // target response outputs + pci_trdy_out, + pci_stop_out, + pci_devsel_out, + pci_trdy_en_out, + pci_stop_en_out, + pci_devsel_en_out, + ad_load_out, + ad_load_on_transfer_out, + // address, data, bus command, byte enable in/outs + pci_ad_reg_in, + pci_ad_out, + pci_ad_en_out, + pci_cbe_reg_in, + pci_cbe_in, + bckp_trdy_en_in, + bckp_devsel_in, + bckp_trdy_in, + bckp_stop_in, + pci_trdy_reg_in, + pci_stop_reg_in, + + // backend side of state machine with control signals to pci_io_mux ... + address_out, + addr_claim_in, + bc_out, + bc0_out, + data_out, + data_in, + be_out, + next_be_out, + req_out, + rdy_out, + addr_phase_out, + bckp_devsel_out, + bckp_trdy_out, + bckp_stop_out, + last_reg_out, + frame_reg_out, + fetch_pcir_fifo_out, + load_medium_reg_out, + sel_fifo_mreg_out, + sel_conf_fifo_out, + load_to_pciw_fifo_out, + load_to_conf_out, + same_read_in, + norm_access_to_config_in, + read_completed_in, + read_processing_in, + target_abort_in, + disconect_wo_data_in, + disconect_w_data_in, + target_abort_set_out, + pciw_fifo_full_in, + pcir_fifo_data_err_in, + wbw_fifo_empty_in, + wbu_del_read_comp_pending_in, + wbu_frame_en_in + +) ; + +/*---------------------------------------------------------------------------------------------------------------------- +Various parameters needed for state machine and other stuff +----------------------------------------------------------------------------------------------------------------------*/ +parameter S_IDLE = 3'b001 ; +parameter S_WAIT = 3'b010 ; +parameter S_TRANSFERE = 3'b100 ; + + +/*================================================================================================================== +System inputs. +==================================================================================================================*/ +// PCI side clock and reset +input clk_in, + reset_in ; + + +/*================================================================================================================== +PCI interface signals - bidirectional signals are divided to inputs and outputs in I/O cells instantiation +module. Enables are separate signals. +==================================================================================================================*/ +// master inputs +input pci_frame_in, + pci_irdy_in, + pci_idsel_in ; +input pci_frame_reg_in, + pci_irdy_reg_in, + pci_idsel_reg_in ; + +// target response outputs +output pci_trdy_out, + pci_stop_out, + pci_devsel_out ; +output pci_trdy_en_out, + pci_stop_en_out, + pci_devsel_en_out ; +output ad_load_out ; +output ad_load_on_transfer_out ; +// address, data, bus command, byte enable in/outs +input [31:0] pci_ad_reg_in ; +output [31:0] pci_ad_out ; +output pci_ad_en_out ; +input [3:0] pci_cbe_reg_in ; +input [3:0] pci_cbe_in ; +input bckp_trdy_en_in ; +input bckp_devsel_in ; +input bckp_trdy_in ; +input bckp_stop_in ; +input pci_trdy_reg_in ; +input pci_stop_reg_in ; + + +/*================================================================================================================== +Other side of PCI Target state machine +==================================================================================================================*/ +// Data, byte enables, bus commands and address ports +output [31:0] address_out ; // current request address output - registered +input addr_claim_in ; // current request address claim input +output [3:0] bc_out ; // current request bus command output - registered +output bc0_out ; // current cycle RW signal output +input [31:0] data_in ; // for read operations - current dataphase data input +output [31:0] data_out ; // for write operations - current request data output - registered +output [3:0] be_out ; // current dataphase byte enable outputs - registered +output [3:0] next_be_out ; // next dataphase byte enable outputs - NOT registered +// Port connection control signals from PCI FSM +output req_out ; // Read is requested to WB master +output rdy_out ; // DATA / ADDRESS selection when read or write - registered +output addr_phase_out ; // Indicates address phase and also fast-back-to-back address phase - registered +output bckp_devsel_out ; // DEVSEL output (which is registered) equivalent +output bckp_trdy_out ; // TRDY output (which is registered) equivalent +output bckp_stop_out ; // STOP output (which is registered) equivalent +output last_reg_out ; // Indicates last data phase - registered +output frame_reg_out ; // FRAME output signal - registered +output fetch_pcir_fifo_out ;// Read enable for PCIR_FIFO when when read is finishen on WB side +output load_medium_reg_out ;// Load data from PCIR_FIFO to medium register (first data must be prepared on time) +output sel_fifo_mreg_out ; // Read data selection between PCIR_FIFO and medium register +output sel_conf_fifo_out ; // Read data selection between Configuration registers and "FIFO" +output load_to_pciw_fifo_out ;// Write enable to PCIW_FIFO +output load_to_conf_out ; // Write enable to Configuration space registers + + +/*================================================================================================================== +Status +==================================================================================================================*/ +input same_read_in ; // Indicates the same read request (important when read is finished on WB side) +input norm_access_to_config_in ; // Indicates the access to Configuration space with MEMORY commands +input read_completed_in ; // Indicates that read request is completed on WB side +input read_processing_in ; // Indicates that read request is processing on WB side +input target_abort_in ; // Indicates target abort termination +input disconect_wo_data_in ; // Indicates disconnect without data termination +input disconect_w_data_in ; // Indicates disconnect with data termination +input pciw_fifo_full_in ; // Indicates that write PCIW_FIFO is full +input pcir_fifo_data_err_in ; // Indicates data error on current data read from PCIR_FIFO +input wbw_fifo_empty_in ; // Indicates that WB SLAVE UNIT has no data to be written to PCI bus +input wbu_del_read_comp_pending_in ; // Indicates that WB SČAVE UNIT has a delayed read pending +input wbu_frame_en_in ; // Indicates that WB SLAVE UNIT is accessing the PCI bus (important if + // address on PCI bus is also claimed by decoder in this PCI TARGET UNIT +output target_abort_set_out ; // Signal used to be set in configuration space registers + +/*================================================================================================================== +END of input / output PORT DEFINITONS !!! +==================================================================================================================*/ + +// Delayed frame signal for determining the address phase +reg previous_frame ; +// Delayed read completed signal for preparing the data from pcir fifo +reg read_completed_reg ; +// Delayed disconnect with/without data for stop loading data to PCIW_FIFO +//reg disconect_wo_data_reg ; + +wire config_disconnect ; +wire disconect_wo_data = disconect_wo_data_in || config_disconnect ; +wire disconect_w_data = disconect_w_data_in ; +// Delayed frame signal for determining the address phase! +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + previous_frame <= #`FF_DELAY 1'b0 ; + read_completed_reg <= #`FF_DELAY 1'b0 ; + end + else + begin + previous_frame <= #`FF_DELAY pci_frame_reg_in ; + read_completed_reg <= #`FF_DELAY read_completed_in ; + end +end + +// Address phase is when previous frame was 1 and this frame is 0 and frame isn't generated from pci master (in WBU) +wire addr_phase = (previous_frame && ~pci_frame_reg_in && ~wbu_frame_en_in) ; + +`ifdef HOST + `ifdef NO_CNF_IMAGE + // Wire tells when there is configuration (read or write) command with IDSEL signal active + wire config_access = 1'b0 ; + // Write and read progresses are used for determining next state + wire write_progress = ( (read_completed_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) || + (~read_processing_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) ) ; + wire read_progress = ( (read_completed_in && wbw_fifo_empty_in) ) ; + `else + // Wire tells when there is configuration (read or write) command with IDSEL signal active + wire config_access = (pci_idsel_reg_in && pci_cbe_reg_in[3]) && (~pci_cbe_reg_in[2] && pci_cbe_reg_in[1]) && // idsel asserted with correct bus command(101x) + (pci_ad_reg_in[1:0] == 2'b00) ; // has to be type 0 configuration cycle + + // Write and read progresses are used for determining next state + wire write_progress = ( (norm_access_to_config_in) || + (read_completed_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) || + (~read_processing_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) ) ; + wire read_progress = ( (~read_completed_in && norm_access_to_config_in) || + (read_completed_in && wbw_fifo_empty_in) ) ; + `endif +`else + // Wire tells when there is configuration (read or write) command with IDSEL signal active + wire config_access = (pci_idsel_reg_in && pci_cbe_reg_in[3]) && (~pci_cbe_reg_in[2] && pci_cbe_reg_in[1]) && // idsel asserted with correct bus command(101x) + (pci_ad_reg_in[1:0] == 2'b00) ; // has to be type 0 configuration cycle + + // Write and read progresses are used for determining next state + wire write_progress = ( (norm_access_to_config_in) || + (read_completed_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) || + (~read_processing_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) ) ; + wire read_progress = ( (~read_completed_in && norm_access_to_config_in) || + (read_completed_in && wbw_fifo_empty_in) ) ; +`endif + +// Signal for loading data to medium register from pcir fifo when read completed from WB side! +wire prepare_rd_fifo_data = (read_completed_in && ~read_completed_reg) ; + +// Write allowed to PCIW_FIFO +wire write_to_fifo = ((read_completed_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in) || + (~read_processing_in && ~pciw_fifo_full_in && ~wbu_del_read_comp_pending_in)) ; +// Read allowed from PCIR_FIFO +wire read_from_fifo = (read_completed_in && wbw_fifo_empty_in) ; +`ifdef HOST + `ifdef NO_CNF_IMAGE + // Read request is allowed to be proceed regarding the WB side + wire read_request = (~read_completed_in && ~read_processing_in) ; + `else + // Read request is allowed to be proceed regarding the WB side + wire read_request = (~read_completed_in && ~read_processing_in && ~norm_access_to_config_in) ; + `endif +`else + // Read request is allowed to be proceed regarding the WB side + wire read_request = (~read_completed_in && ~read_processing_in && ~norm_access_to_config_in) ; +`endif + +// Critically calculated signals are latched in this clock period (address phase) to be used in the next clock period +reg rw_cbe0 ; +reg wr_progress ; +reg rd_progress ; +reg rd_from_fifo ; +reg rd_request ; +reg wr_to_fifo ; +reg same_read_reg ; + +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + rw_cbe0 <= #`FF_DELAY 1'b0 ; + wr_progress <= #`FF_DELAY 1'b0 ; + rd_progress <= #`FF_DELAY 1'b0 ; + rd_from_fifo <= #`FF_DELAY 1'b0 ; + rd_request <= #`FF_DELAY 1'b0 ; + wr_to_fifo <= #`FF_DELAY 1'b0 ; + same_read_reg <= #`FF_DELAY 1'b0 ; + end + else + begin + if (addr_phase) + begin + rw_cbe0 <= #`FF_DELAY pci_cbe_reg_in[0] ; + wr_progress <= #`FF_DELAY write_progress ; + rd_progress <= #`FF_DELAY read_progress ; + rd_from_fifo <= #`FF_DELAY read_from_fifo ; + rd_request <= #`FF_DELAY read_request ; + wr_to_fifo <= #`FF_DELAY write_to_fifo ; + same_read_reg <= #`FF_DELAY same_read_in ; + end + end +end + +`ifdef HOST + `ifdef NO_CNF_IMAGE + wire norm_access_to_conf_reg = 1'b0 ; + wire cnf_progress = 1'b0 ; + `else + reg norm_access_to_conf_reg ; + reg cnf_progress ; + always@(posedge clk_in or posedge reset_in) + begin + if (reset_in) + begin + norm_access_to_conf_reg <= #`FF_DELAY 1'b0 ; + cnf_progress <= #`FF_DELAY 1'b0 ; + end + else + begin + if (addr_phase) + begin + norm_access_to_conf_reg <= #`FF_DELAY norm_access_to_config_in ; + cnf_progress <= #`FF_DELAY config_access ; + end + end + end + `endif +`else + reg norm_access_to_conf_reg ; + reg cnf_progress ; + always@(posedge clk_in or posedge reset_in) + begin + if (reset_in) + begin + norm_access_to_conf_reg <= #`FF_DELAY 1'b0 ; + cnf_progress <= #`FF_DELAY 1'b0 ; + end + else + begin + if (addr_phase) + begin + norm_access_to_conf_reg <= #`FF_DELAY norm_access_to_config_in ; + cnf_progress <= #`FF_DELAY config_access ; + end + end + end +`endif + +// Signal used in S_WAIT state to determin next state +wire s_wait_progress = ( + (~cnf_progress && rw_cbe0 && wr_progress && ~target_abort_in) || + (~cnf_progress && ~rw_cbe0 && same_read_reg && rd_progress && ~target_abort_in && ~pcir_fifo_data_err_in) || + (~cnf_progress && ~rw_cbe0 && ~same_read_reg && norm_access_to_conf_reg && ~target_abort_in) || + (cnf_progress && ~target_abort_in) + ) ; + +// Signal used in S_TRANSFERE state to determin next state +wire s_tran_progress = ( + (rw_cbe0 && !disconect_wo_data) || + (~rw_cbe0 && !disconect_wo_data && !target_abort_in && !pcir_fifo_data_err_in) + ) ; + +// Clock enable for PCI state machine driven directly from critical inputs - FRAME and IRDY +wire pcit_sm_clk_en ; +// FSM states signals indicating the current state +reg state_idle ; +reg state_wait ; +reg sm_transfere ; +reg backoff ; +reg state_default ; +wire state_backoff = sm_transfere && backoff ; +wire state_transfere = sm_transfere && !backoff ; + +always@(posedge clk_in or posedge reset_in) +begin + if ( reset_in ) + backoff <= #`FF_DELAY 1'b0 ; + else if ( state_idle ) + backoff <= #`FF_DELAY 1'b0 ; + else + backoff <= #`FF_DELAY (state_wait && !s_wait_progress) || + (sm_transfere && !s_tran_progress && !pci_frame_in && !pci_irdy_in) || + backoff ; +end +assign config_disconnect = sm_transfere && (norm_access_to_conf_reg || cnf_progress) ; + +// Clock enable module used for preserving the architecture because of minimum delay for critical inputs +pci_target32_clk_en pci_target_clock_en +( + .addr_phase (addr_phase), + .config_access (config_access), + .addr_claim_in (addr_claim_in), + .pci_frame_in (pci_frame_in), + .state_wait (state_wait), + .state_transfere (sm_transfere), + .state_default (state_default), + .clk_enable (pcit_sm_clk_en) +); + +reg [2:0] c_state ; //current state register +reg [2:0] n_state ; //next state input to current state register + +// state machine register control +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) // reset state machine to S_IDLE state + c_state <= #`FF_DELAY S_IDLE ; + else + if (pcit_sm_clk_en) // if conditions are true, then FSM goes to next state! + c_state <= #`FF_DELAY n_state ; +end + +// state machine logic +always@(c_state) +begin + case (c_state) + S_IDLE : + begin + state_idle <= 1'b1 ; + state_wait <= 1'b0 ; + sm_transfere <= 1'b0 ; + state_default <= 1'b0 ; + n_state <= S_WAIT ; + end + S_WAIT : + begin + state_idle <= 1'b0 ; + state_wait <= 1'b1 ; + sm_transfere <= 1'b0 ; + state_default <= 1'b0 ; + n_state <= S_TRANSFERE ; + end + S_TRANSFERE : + begin + state_idle <= 1'b0 ; + state_wait <= 1'b0 ; + sm_transfere <= 1'b1 ; + state_default <= 1'b0 ; + n_state <= S_IDLE ; + end + default : + begin + state_idle <= 1'b0 ; + state_wait <= 1'b0 ; + sm_transfere <= 1'b0 ; + state_default <= 1'b1 ; + n_state <= S_IDLE ; + end + endcase +end + + // if not retry and not target abort + // NO CRITICAL SIGNALS +wire trdy_w = ( + (state_wait && ~cnf_progress && rw_cbe0 && wr_progress && ~target_abort_in) || + (state_wait && ~cnf_progress && ~rw_cbe0 && same_read_reg && rd_progress && ~target_abort_in && !pcir_fifo_data_err_in) || + (state_wait && ~cnf_progress && ~rw_cbe0 && ~same_read_reg && norm_access_to_conf_reg && ~target_abort_in) || + (state_wait && cnf_progress && ~target_abort_in) + ) ; + // if not disconnect without data and not target abort (only during reads) + // MUST BE ANDED WITH CRITICAL ~FRAME +wire trdy_w_frm = ( + (state_transfere && !cnf_progress && !norm_access_to_conf_reg && rw_cbe0 && !disconect_wo_data) || + (state_transfere && !cnf_progress && !norm_access_to_conf_reg && ~rw_cbe0 && !disconect_wo_data && ~pcir_fifo_data_err_in) || + (state_transfere && !cnf_progress && !norm_access_to_conf_reg && disconect_w_data && pci_irdy_reg_in && + ((~rw_cbe0 && ~pcir_fifo_data_err_in) || rw_cbe0)) + ) ; + // if not disconnect without data and not target abort (only during reads) + // MUST BE ANDED WITH CRITICAL ~FRAME AND IRDY +wire trdy_w_frm_irdy = ( ~bckp_trdy_in ) ; +// TRDY critical module used for preserving the architecture because of minimum delay for critical inputs +pci_target32_trdy_crit pci_target_trdy_critical +( + .trdy_w (trdy_w), + .trdy_w_frm (trdy_w_frm), + .trdy_w_frm_irdy (trdy_w_frm_irdy), + .pci_frame_in (pci_frame_in), + .pci_irdy_in (pci_irdy_in), + .pci_trdy_out (pci_trdy_out) +); + + // if target abort or retry + // NO CRITICAL SIGNALS +wire stop_w = ( + (state_wait && target_abort_in) || + (state_wait && ~cnf_progress && rw_cbe0 && ~wr_progress) || + (state_wait && ~cnf_progress && ~rw_cbe0 && same_read_reg && ~rd_progress) || + (state_wait && ~cnf_progress && ~rw_cbe0 && same_read_reg && rd_progress && pcir_fifo_data_err_in) || + (state_wait && ~cnf_progress && ~rw_cbe0 && ~same_read_reg && ~norm_access_to_conf_reg) + ) ; + // if asserted, wait for deactivating the frame + // MUST BE ANDED WITH CRITICAL ~FRAME +wire stop_w_frm = ( + (state_backoff && ~bckp_stop_in) + ) ; + // if target abort or if disconnect without data (after data transfere) + // MUST BE ANDED WITH CRITICAL ~FRAME AND ~IRDY +wire stop_w_frm_irdy = ( + (state_transfere && (disconect_wo_data)) || + (state_transfere && ~rw_cbe0 && pcir_fifo_data_err_in) + ) ; +// STOP critical module used for preserving the architecture because of minimum delay for critical inputs +pci_target32_stop_crit pci_target_stop_critical +( + .stop_w (stop_w), + .stop_w_frm (stop_w_frm), + .stop_w_frm_irdy (stop_w_frm_irdy), + .pci_frame_in (pci_frame_in), + .pci_irdy_in (pci_irdy_in), + .pci_stop_out (pci_stop_out) +); + + // if OK to respond and not target abort + // NO CRITICAL SIGNALS +wire devs_w = ( + (addr_phase && config_access) || + (addr_phase && ~config_access && addr_claim_in) || + (state_wait && ~target_abort_in && !(~cnf_progress && ~rw_cbe0 && same_read_reg && rd_progress && pcir_fifo_data_err_in) ) + ) ; + + // if not target abort (only during reads) or if asserted, wait for deactivating the frame + // MUST BE ANDED WITH CRITICAL ~FRAME +wire devs_w_frm = ( + (state_transfere && rw_cbe0) || + (state_transfere && ~rw_cbe0 && ~pcir_fifo_data_err_in) || + (state_backoff && ~bckp_devsel_in) + ) ; + // if not target abort (only during reads) + // MUST BE ANDED WITH CRITICAL ~FRAME AND IRDY +wire devs_w_frm_irdy = ( + (state_transfere && ~rw_cbe0 && pcir_fifo_data_err_in) + ) ; +// DEVSEL critical module used for preserving the architecture because of minimum delay for critical inputs +pci_target32_devs_crit pci_target_devsel_critical +( + .devs_w (devs_w), + .devs_w_frm (devs_w_frm), + .devs_w_frm_irdy (devs_w_frm_irdy), + .pci_frame_in (pci_frame_in), + .pci_irdy_in (pci_irdy_in), + .pci_devsel_out (pci_devsel_out) +); + +// signal used in AD enable module with preserving the hierarchy because of minimum delay for critical inputs +assign pci_ad_en_out = ( + (addr_phase && config_access && ~pci_cbe_reg_in[0]) || + (addr_phase && ~config_access && addr_claim_in && ~pci_cbe_reg_in[0]) || + (state_wait && ~rw_cbe0) || + (state_transfere && ~rw_cbe0) || + (state_backoff && ~rw_cbe0 && ~pci_frame_reg_in) + ) ; + +wire fast_back_to_back = (addr_phase && ~pci_irdy_reg_in) ; + + // if cycle will progress or will not be stopped + // NO CRITICAL SIGNALS +wire ctrl_en = + /*(~wbu_frame_en_in && fast_back_to_back) ||*/ + (addr_phase && config_access) || + (addr_phase && ~config_access && addr_claim_in) || + (state_wait) || + (state_transfere && ~(pci_frame_reg_in && ~pci_irdy_reg_in && (~pci_stop_reg_in || ~pci_trdy_reg_in))) || + (state_backoff && ~(pci_frame_reg_in && ~pci_irdy_reg_in && (~pci_stop_reg_in || ~pci_trdy_reg_in))) ; + +assign pci_trdy_en_out = ctrl_en ; +assign pci_stop_en_out = ctrl_en ; +assign pci_devsel_en_out = ctrl_en ; + +// target ready output signal delayed for one clock used in conjunction with irdy_reg to select which +// data are registered in io mux module - from fifo or medoum register +reg bckp_trdy_reg ; +// delayed indicators for states transfere and backoff +reg state_transfere_reg ; +reg state_backoff_reg ; +always@(posedge clk_in or posedge reset_in) +begin + if (reset_in) + begin + bckp_trdy_reg <= #`FF_DELAY 1'b1 ; + state_transfere_reg <= #`FF_DELAY 1'b0 ; + state_backoff_reg <= #`FF_DELAY 1'b0 ; + end + else + begin + bckp_trdy_reg <= #`FF_DELAY bckp_trdy_in ; + state_transfere_reg <= #`FF_DELAY state_transfere ; + state_backoff_reg <= #`FF_DELAY state_backoff ; + end +end + +// Read control signals assignments +assign + fetch_pcir_fifo_out = ( + (prepare_rd_fifo_data) || + (state_wait && ~cnf_progress && ~rw_cbe0 && same_read_reg && rd_from_fifo && ~target_abort_in) || + (bckp_trdy_en_in && ~pci_trdy_reg_in && ~cnf_progress && ~rw_cbe0 && same_read_reg && rd_from_fifo && ~pci_irdy_reg_in) + ) ; + +assign ad_load_out = (state_wait) ; + +assign ad_load_on_transfer_out = (bckp_trdy_en_in && ~rw_cbe0) ; + +assign load_medium_reg_out = ( + (prepare_rd_fifo_data) || + (state_wait && ~rw_cbe0 && ~cnf_progress && same_read_reg && rd_from_fifo && ~target_abort_in) || + (~pci_irdy_reg_in && ~rw_cbe0 && ~cnf_progress && same_read_reg && rd_from_fifo && ~pci_trdy_reg_in && bckp_trdy_en_in) + ) ; + +assign sel_fifo_mreg_out = (~pci_irdy_reg_in && ~bckp_trdy_reg) ; + +`ifdef HOST + `ifdef NO_CNF_IMAGE + assign sel_conf_fifo_out = 1'b0 ; + `else + assign sel_conf_fifo_out = (cnf_progress || norm_access_to_conf_reg) ; + `endif +`else + assign sel_conf_fifo_out = (cnf_progress || norm_access_to_conf_reg) ; +`endif + +// Write control signals assignments +assign + load_to_pciw_fifo_out = ( + (state_wait && (~cnf_progress && ~norm_access_to_conf_reg) && rw_cbe0 && wr_to_fifo && ~target_abort_in) || + (state_transfere_reg && ~state_backoff && rw_cbe0 && wr_to_fifo /*&& ~disconect_wo_data_reg*/ && ~pci_irdy_reg_in && ~bckp_trdy_reg && (~cnf_progress && ~norm_access_to_conf_reg)) || + ((state_backoff || state_backoff_reg) && rw_cbe0 && wr_to_fifo && ~pci_irdy_reg_in && ~bckp_trdy_reg && (~cnf_progress && ~norm_access_to_conf_reg)) + ) ; + +`ifdef HOST + `ifdef NO_CNF_IMAGE + assign load_to_conf_out = 1'b0 ; + `else + assign load_to_conf_out = ( + (state_transfere_reg && cnf_progress && rw_cbe0 && ~pci_irdy_reg_in && ~bckp_trdy_reg) || + (state_transfere_reg && norm_access_to_conf_reg && rw_cbe0 && ~pci_irdy_reg_in && ~bckp_trdy_reg) + ) ; + `endif +`else + assign load_to_conf_out = ( + (state_transfere_reg && cnf_progress && rw_cbe0 && ~pci_irdy_reg_in && ~bckp_trdy_reg) || + (state_transfere_reg && norm_access_to_conf_reg && rw_cbe0 && ~pci_irdy_reg_in && ~bckp_trdy_reg) + ) ; +`endif + +// General control sigal assignments +assign addr_phase_out = addr_phase ; +assign last_reg_out = (pci_frame_reg_in && ~pci_irdy_reg_in) ; +assign frame_reg_out = pci_frame_reg_in ; +assign bckp_devsel_out = bckp_devsel_in ; +assign bckp_trdy_out = bckp_trdy_in ; +assign bckp_stop_out = bckp_stop_in ; +assign target_abort_set_out = (bckp_devsel_in && bckp_trdy_in && ~bckp_stop_in && bckp_trdy_en_in) ; +// request signal for delayed sinc. module +reg master_will_request_read ; +always@(posedge clk_in or posedge reset_in) +begin + if ( reset_in ) + master_will_request_read <= #`FF_DELAY 1'b0 ; + else + master_will_request_read <= #`FF_DELAY ((state_wait && ~target_abort_in) || (state_backoff && ~target_abort_set_out)) && ~cnf_progress && ~norm_access_to_conf_reg && ~rw_cbe0 && rd_request ; +end +// MORE OPTIMIZED READS, but not easy to control in a testbench! +//assign req_out = master_will_request_read ; +assign req_out = master_will_request_read && !pci_irdy_reg_in && !read_processing_in ; + +// ready tells when address or data are written into fifo - RDY ? DATA : ADDRESS +assign rdy_out = ~bckp_trdy_reg ; + +// data and address outputs assignments! +assign pci_ad_out = data_in ; + +assign data_out = pci_ad_reg_in ; +assign be_out = pci_cbe_reg_in ; +assign next_be_out = pci_cbe_in ; +assign address_out = pci_ad_reg_in ; +assign bc_out = pci_cbe_reg_in ; +assign bc0_out = rw_cbe0 ; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v new file mode 100644 index 000000000..22ef867e2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_stop_crit.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_stop_crit.v,v $ +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_stop_crit +( + stop_w, + stop_w_frm, + stop_w_frm_irdy, + pci_frame_in, + pci_irdy_in, + pci_stop_out +); + +input stop_w ; // stop signal (composed without critical signals) that do not need critical inputs +input stop_w_frm ; // stop signal (composed without critical signals) that needs AND with critical FRAME input +input stop_w_frm_irdy ; // stop signal (composed without critical signals) that needs AND with critical FRAME and + // IRDY inputs +input pci_frame_in ; // critical constrained input signal +input pci_irdy_in ; // critical constrained input signal + +output pci_stop_out ; // PCI stop output + +// PCI stop output with preserved hierarchy for minimum delay! +assign pci_stop_out = ~(stop_w || (stop_w_frm && ~pci_frame_in) || (stop_w_frm_irdy && ~pci_frame_in && ~pci_irdy_in)) ; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v new file mode 100644 index 000000000..ab96c0357 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target32_trdy_crit.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target32_trdy_crit.v,v $ +// Revision 1.4 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// module is used to separate logic which uses criticaly constrained inputs from slower logic. +// It is used to synthesize critical timing logic separately with faster cells or without optimization + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target32_trdy_crit +( + trdy_w, + trdy_w_frm, + trdy_w_frm_irdy, + pci_frame_in, + pci_irdy_in, + pci_trdy_out +); + +input trdy_w ; // trdy signal (composed without critical signals) that do not need critical inputs +input trdy_w_frm ; // trdy signal (composed without critical signals) that needs AND with critical FRAME input +input trdy_w_frm_irdy ; // trdy signal (composed without critical signals) that needs AND with critical FRAME and + // IRDY inputs +input pci_frame_in ; // critical constrained input signal +input pci_irdy_in ; // critical constrained input signal + +output pci_trdy_out ; // PCI trdy output + +// PCI trdy output with preserved hierarchy for minimum delay! +assign pci_trdy_out = ~(trdy_w || (trdy_w_frm && ~pci_frame_in) || (trdy_w_frm_irdy && ~pci_frame_in && pci_irdy_in)) ; + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v new file mode 100644 index 000000000..27cc6ef7c --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v @@ -0,0 +1,946 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: pci_target_unit.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_target_unit.v,v $ +// Revision 1.16 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.15 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.14 2003/10/17 09:11:52 markom +// mbist signals updated according to newest convention +// +// Revision 1.13 2003/08/21 20:55:14 tadejm +// Corrected bug when writing to FIFO (now it is registered). +// +// Revision 1.12 2003/08/08 16:36:33 tadejm +// Added 'three_left_out' to pci_pciw_fifo signaling three locations before full. Added comparison between current registered cbe and next unregistered cbe to signal wb_master whether it is allowed to performe burst or not. Due to this, I needed 'three_left_out' so that writing to pci_pciw_fifo can be registered, otherwise timing problems would occure. +// +// Revision 1.11 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.10 2002/10/18 03:36:37 tadejm +// Changed wrong signal name mbist_sen into mbist_ctrl_i. +// +// Revision 1.9 2002/10/17 22:51:08 tadejm +// Changed BIST signals for RAMs. +// +// Revision 1.8 2002/10/11 10:09:01 mihad +// Added additional testcase and changed rst name in BIST to trst +// +// Revision 1.7 2002/10/08 17:17:05 mihad +// Added BIST signals for RAMs. +// +// Revision 1.6 2002/09/25 15:53:52 mihad +// Removed all logic from asynchronous reset network +// +// Revision 1.5 2002/03/05 11:53:47 mihad +// Added some testcases, removed un-needed fifo signals +// +// Revision 1.4 2002/02/19 16:32:37 mihad +// Modified testbench and fixed some bugs +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// Module instantiates and connects other modules lower in hierarcy +// PCI target unit consists of modules that together form datapath +// between external WISHBONE slaves and external PCI initiators +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_target_unit +( + reset_in, + wb_clock_in, + pci_clock_in, + + pciu_wbm_adr_o, + pciu_wbm_dat_o, + pciu_wbm_dat_i, + pciu_wbm_cyc_o, + pciu_wbm_stb_o, + pciu_wbm_we_o, + pciu_wbm_cti_o, + pciu_wbm_bte_o, + pciu_wbm_sel_o, + pciu_wbm_ack_i, + pciu_wbm_rty_i, + pciu_wbm_err_i, + pciu_mem_enable_in, + pciu_io_enable_in, + pciu_map_in, + pciu_pref_en_in, + pciu_conf_data_in, + pciu_wbw_fifo_empty_in, + pciu_wbu_del_read_comp_pending_in, + pciu_wbu_frame_en_in, + pciu_bar0_in, + pciu_bar1_in, + pciu_bar2_in, + pciu_bar3_in, + pciu_bar4_in, + pciu_bar5_in, + pciu_am0_in, + pciu_am1_in, + pciu_am2_in, + pciu_am3_in, + pciu_am4_in, + pciu_am5_in, + pciu_ta0_in, + pciu_ta1_in, + pciu_ta2_in, + pciu_ta3_in, + pciu_ta4_in, + pciu_ta5_in, + pciu_at_en_in, + pciu_cache_line_size_in, + pciu_cache_lsize_not_zero_in, + pciu_pciif_frame_in, + pciu_pciif_irdy_in, + pciu_pciif_idsel_in, + pciu_pciif_frame_reg_in, + pciu_pciif_irdy_reg_in, + pciu_pciif_idsel_reg_in, + pciu_pciif_ad_reg_in, + pciu_pciif_cbe_reg_in, + pciu_pciif_cbe_in, + pciu_pciif_bckp_trdy_en_in, + pciu_pciif_bckp_devsel_in, + pciu_pciif_bckp_trdy_in, + pciu_pciif_bckp_stop_in, + pciu_pciif_trdy_reg_in, + pciu_pciif_stop_reg_in, + pciu_pciif_trdy_out, + pciu_pciif_stop_out, + pciu_pciif_devsel_out, + pciu_pciif_trdy_en_out, + pciu_pciif_stop_en_out, + pciu_pciif_devsel_en_out, + pciu_ad_load_out, + pciu_ad_load_on_transfer_out, + pciu_pciif_ad_out, + pciu_pciif_ad_en_out, + pciu_pciif_tabort_set_out, + pciu_err_addr_out, + pciu_err_bc_out, + pciu_err_data_out, + pciu_err_be_out, + pciu_err_signal_out, + pciu_err_source_out, + pciu_err_rty_exp_out, + pciu_conf_offset_out, + pciu_conf_renable_out, + pciu_conf_wenable_out, + pciu_conf_be_out, + pciu_conf_data_out, + pciu_pci_drcomp_pending_out, + pciu_pciw_fifo_empty_out + +`ifdef PCI_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif +); + +`ifdef HOST + `ifdef NO_CNF_IMAGE + parameter pci_ba0_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + `else + parameter pci_ba0_width = 20 ; + `endif +`endif + +`ifdef GUEST + parameter pci_ba0_width = 20 ; +`endif + +parameter pci_ba1_5_width = `PCI_NUM_OF_DEC_ADDR_LINES ; + +input reset_in, + wb_clock_in, + pci_clock_in ; + +output [31:0] pciu_wbm_adr_o ; +output [31:0] pciu_wbm_dat_o ; +input [31:0] pciu_wbm_dat_i ; +output pciu_wbm_cyc_o ; +output pciu_wbm_stb_o ; +output pciu_wbm_we_o ; +output [2:0] pciu_wbm_cti_o ; +output [1:0] pciu_wbm_bte_o ; +output [3:0] pciu_wbm_sel_o ; +input pciu_wbm_ack_i ; +input pciu_wbm_rty_i ; +input pciu_wbm_err_i ; + +input pciu_wbw_fifo_empty_in ; +input pciu_wbu_del_read_comp_pending_in ; +input pciu_wbu_frame_en_in ; + +input pciu_mem_enable_in ; +input pciu_io_enable_in ; +input [5:0] pciu_map_in ; +input [5:0] pciu_pref_en_in ; +input [31:0] pciu_conf_data_in ; + +input [pci_ba0_width - 1:0] pciu_bar0_in ; +input [pci_ba1_5_width - 1:0] pciu_bar1_in ; +input [pci_ba1_5_width - 1:0] pciu_bar2_in ; +input [pci_ba1_5_width - 1:0] pciu_bar3_in ; +input [pci_ba1_5_width - 1:0] pciu_bar4_in ; +input [pci_ba1_5_width - 1:0] pciu_bar5_in ; +input [pci_ba1_5_width - 1:0] pciu_am0_in ; +input [pci_ba1_5_width - 1:0] pciu_am1_in ; +input [pci_ba1_5_width - 1:0] pciu_am2_in ; +input [pci_ba1_5_width - 1:0] pciu_am3_in ; +input [pci_ba1_5_width - 1:0] pciu_am4_in ; +input [pci_ba1_5_width - 1:0] pciu_am5_in ; +input [pci_ba1_5_width - 1:0] pciu_ta0_in ; +input [pci_ba1_5_width - 1:0] pciu_ta1_in ; +input [pci_ba1_5_width - 1:0] pciu_ta2_in ; +input [pci_ba1_5_width - 1:0] pciu_ta3_in ; +input [pci_ba1_5_width - 1:0] pciu_ta4_in ; +input [pci_ba1_5_width - 1:0] pciu_ta5_in ; +input [5:0] pciu_at_en_in ; + +input [7:0] pciu_cache_line_size_in ; +input pciu_cache_lsize_not_zero_in ; + +input pciu_pciif_frame_in ; +input pciu_pciif_irdy_in ; +input pciu_pciif_idsel_in ; +input pciu_pciif_frame_reg_in ; +input pciu_pciif_irdy_reg_in ; +input pciu_pciif_idsel_reg_in ; +input [31:0] pciu_pciif_ad_reg_in ; +input [3:0] pciu_pciif_cbe_reg_in ; +input [3:0] pciu_pciif_cbe_in; +input pciu_pciif_bckp_trdy_en_in ; +input pciu_pciif_bckp_devsel_in ; +input pciu_pciif_bckp_trdy_in ; +input pciu_pciif_bckp_stop_in ; +input pciu_pciif_trdy_reg_in ; +input pciu_pciif_stop_reg_in ; + + +output pciu_pciif_trdy_out ; +output pciu_pciif_stop_out ; +output pciu_pciif_devsel_out ; +output pciu_pciif_trdy_en_out ; +output pciu_pciif_stop_en_out ; +output pciu_pciif_devsel_en_out ; +output pciu_ad_load_out ; +output pciu_ad_load_on_transfer_out ; +output [31:0] pciu_pciif_ad_out ; +output pciu_pciif_ad_en_out ; +output pciu_pciif_tabort_set_out ; + +output [31:0] pciu_err_addr_out ; +output [3:0] pciu_err_bc_out ; +output [31:0] pciu_err_data_out ; +output [3:0] pciu_err_be_out ; +output pciu_err_signal_out ; +output pciu_err_source_out ; +output pciu_err_rty_exp_out ; + +output [11:0] pciu_conf_offset_out ; +output pciu_conf_renable_out ; +output pciu_conf_wenable_out ; +output [3:0] pciu_conf_be_out ; +output [31:0] pciu_conf_data_out ; + +output pciu_pci_drcomp_pending_out ; +output pciu_pciw_fifo_empty_out ; + +`ifdef PCI_BIST +/*----------------------------------------------------- +BIST debug chain port signals +-----------------------------------------------------*/ +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + + +// pci target state machine and interface outputs +wire pcit_sm_trdy_out ; +wire pcit_sm_stop_out ; +wire pcit_sm_devsel_out ; +wire pcit_sm_trdy_en_out ; +wire pcit_sm_stop_en_out ; +wire pcit_sm_devsel_en_out ; +wire pcit_sm_ad_load_out ; +wire pcit_sm_ad_load_on_transfer_out ; +wire [31:0] pcit_sm_ad_out ; +wire pcit_sm_ad_en_out ; +wire [31:0] pcit_sm_address_out ; +wire [3:0] pcit_sm_bc_out ; +wire pcit_sm_bc0_out ; +wire [31:0] pcit_sm_data_out ; +wire [3:0] pcit_sm_be_out ; +wire [3:0] pcit_sm_next_be_out ; +wire pcit_sm_req_out ; +wire pcit_sm_rdy_out ; +wire pcit_sm_addr_phase_out ; +wire pcit_sm_bckp_devsel_out ; +wire pcit_sm_bckp_trdy_out ; +wire pcit_sm_bckp_stop_out ; +wire pcit_sm_last_reg_out ; +wire pcit_sm_frame_reg_out ; +wire pcit_sm_fetch_pcir_fifo_out ; +wire pcit_sm_load_medium_reg_out ; +wire pcit_sm_sel_fifo_mreg_out ; +wire pcit_sm_sel_conf_fifo_out ; +wire pcit_sm_load_to_pciw_fifo_out ; +wire pcit_sm_load_to_conf_out ; + +wire pcit_sm_target_abort_set_out ; // to conf space + +assign pciu_pciif_trdy_out = pcit_sm_trdy_out ; +assign pciu_pciif_stop_out = pcit_sm_stop_out ; +assign pciu_pciif_devsel_out = pcit_sm_devsel_out ; +assign pciu_pciif_trdy_en_out = pcit_sm_trdy_en_out ; +assign pciu_pciif_stop_en_out = pcit_sm_stop_en_out ; +assign pciu_pciif_devsel_en_out = pcit_sm_devsel_en_out ; +assign pciu_ad_load_out = pcit_sm_ad_load_out ; +assign pciu_ad_load_on_transfer_out = pcit_sm_ad_load_on_transfer_out ; +assign pciu_pciif_ad_out = pcit_sm_ad_out ; +assign pciu_pciif_ad_en_out = pcit_sm_ad_en_out ; +assign pciu_pciif_tabort_set_out = pcit_sm_target_abort_set_out ; + +wire pcit_if_addr_claim_out ; +wire [31:0] pcit_if_data_out ; +wire pcit_if_same_read_out ; +wire pcit_if_norm_access_to_config_out ; +wire pcit_if_read_completed_out ; +wire pcit_if_read_processing_out ; +wire pcit_if_target_abort_out ; +wire pcit_if_disconect_wo_data_out ; +wire pcit_if_disconect_w_data_out ; +wire pcit_if_pciw_fifo_full_out ; +wire pcit_if_pcir_fifo_data_err_out ; +wire pcit_if_wbw_fifo_empty_out ; +wire pcit_if_wbu_del_read_comp_pending_out ; +wire pcit_if_req_out ; +wire pcit_if_done_out ; +wire pcit_if_in_progress_out ; +wire [31:0] pcit_if_addr_out ; +wire [3:0] pcit_if_be_out ; +wire pcit_if_we_out ; +wire [3:0] pcit_if_bc_out ; +wire pcit_if_burst_ok_out ; +wire pcit_if_pcir_fifo_renable_out ; +wire pcit_if_pcir_fifo_flush_out ; +wire pcit_if_pciw_fifo_wenable_out ; +wire [31:0] pcit_if_pciw_fifo_addr_data_out ; +wire [3:0] pcit_if_pciw_fifo_cbe_out ; +wire [3:0] pcit_if_pciw_fifo_control_out ; +wire [11:0] pcit_if_conf_addr_out ; +wire [31:0] pcit_if_conf_data_out ; +wire [3:0] pcit_if_conf_be_out ; +wire pcit_if_conf_we_out ; +wire pcit_if_conf_re_out ; + +// pci target state machine outputs +// pci interface signals +assign pciu_conf_offset_out = pcit_if_conf_addr_out ; +assign pciu_conf_renable_out = pcit_if_conf_re_out ; +assign pciu_conf_wenable_out = pcit_if_conf_we_out ; +assign pciu_conf_be_out = pcit_if_conf_be_out ; +assign pciu_conf_data_out = pcit_if_conf_data_out ; + +// wishbone master state machine outputs +wire wbm_sm_wb_read_done ; +wire wbm_sm_write_attempt ; +wire wbm_sm_pcir_fifo_wenable_out ; +wire [31:0] wbm_sm_pcir_fifo_data_out ; +wire [3:0] wbm_sm_pcir_fifo_be_out ; +wire [3:0] wbm_sm_pcir_fifo_control_out ; +wire wbm_sm_pciw_fifo_renable_out ; +wire wbm_sm_pci_error_sig_out ; +wire [3:0] wbm_sm_pci_error_bc ; +wire wbm_sm_write_rty_cnt_exp_out ; +wire wbm_sm_error_source_out ; +wire wbm_sm_read_rty_cnt_exp_out ; +wire wbm_sm_cyc_out ; +wire wbm_sm_stb_out ; +wire wbm_sm_we_out ; +wire [2:0] wbm_sm_cti_out ; +wire [1:0] wbm_sm_bte_out ; +wire [3:0] wbm_sm_sel_out ; +wire [31:0] wbm_sm_adr_out ; +wire [31:0] wbm_sm_mdata_out ; + +assign pciu_err_addr_out = wbm_sm_adr_out ; +assign pciu_err_bc_out = wbm_sm_pci_error_bc ; +assign pciu_err_data_out = wbm_sm_mdata_out ; +assign pciu_err_be_out = ~wbm_sm_sel_out ; +assign pciu_err_signal_out = wbm_sm_pci_error_sig_out ; +assign pciu_err_source_out = wbm_sm_error_source_out ; +assign pciu_err_rty_exp_out = wbm_sm_write_rty_cnt_exp_out ; + +assign pciu_wbm_adr_o = wbm_sm_adr_out ; +assign pciu_wbm_dat_o = wbm_sm_mdata_out ; +assign pciu_wbm_cyc_o = wbm_sm_cyc_out ; +assign pciu_wbm_stb_o = wbm_sm_stb_out ; +assign pciu_wbm_we_o = wbm_sm_we_out ; +assign pciu_wbm_cti_o = wbm_sm_cti_out ; +assign pciu_wbm_bte_o = wbm_sm_bte_out ; +assign pciu_wbm_sel_o = wbm_sm_sel_out ; + +// pciw_pcir fifo outputs + +// pciw_fifo_outputs: +wire [31:0] fifos_pciw_addr_data_out ; +wire [3:0] fifos_pciw_cbe_out ; +wire [3:0] fifos_pciw_control_out ; +wire fifos_pciw_three_left_out ; +wire fifos_pciw_two_left_out ; +wire fifos_pciw_almost_full_out ; +wire fifos_pciw_full_out ; +wire fifos_pciw_almost_empty_out ; +wire fifos_pciw_empty_out ; +wire fifos_pciw_transaction_ready_out ; + +assign pciu_pciw_fifo_empty_out = !wbm_sm_write_attempt; + +// pcir_fifo_outputs +wire [31:0] fifos_pcir_data_out ; +wire [3:0] fifos_pcir_be_out ; +wire [3:0] fifos_pcir_control_out ; +wire fifos_pcir_almost_empty_out ; +wire fifos_pcir_empty_out ; + +// delayed transaction logic outputs +wire [31:0] del_sync_addr_out ; +wire [3:0] del_sync_be_out ; +wire del_sync_we_out ; +wire del_sync_comp_req_pending_out ; +wire del_sync_comp_comp_pending_out ; +wire del_sync_req_req_pending_out ; +wire del_sync_req_comp_pending_out ; +wire [3:0] del_sync_bc_out ; +wire del_sync_status_out ; +wire del_sync_comp_flush_out ; +wire del_sync_burst_out ; + +assign pciu_pci_drcomp_pending_out = del_sync_comp_comp_pending_out ; + +// WISHBONE master interface inputs +wire wbm_sm_pci_tar_read_request = del_sync_comp_req_pending_out ; +wire [31:0] wbm_sm_pci_tar_address = del_sync_addr_out ; +wire [3:0] wbm_sm_pci_tar_cmd = del_sync_bc_out ; +wire [3:0] wbm_sm_pci_tar_be = del_sync_be_out ; +wire wbm_sm_pci_tar_burst_ok = del_sync_burst_out ; +wire [7:0] wbm_sm_pci_cache_line_size = pciu_cache_line_size_in ; +wire wbm_sm_cache_lsize_not_zero_in = pciu_cache_lsize_not_zero_in ; +wire [31:0] wbm_sm_pciw_fifo_addr_data_in = fifos_pciw_addr_data_out ; +wire [3:0] wbm_sm_pciw_fifo_cbe_in = fifos_pciw_cbe_out ; +wire [3:0] wbm_sm_pciw_fifo_control_in = fifos_pciw_control_out ; +wire wbm_sm_pciw_fifo_almost_empty_in = fifos_pciw_almost_empty_out ; +wire wbm_sm_pciw_fifo_empty_in = fifos_pciw_empty_out ; +wire wbm_sm_pciw_fifo_transaction_ready_in = fifos_pciw_transaction_ready_out ; +wire [31:0] wbm_sm_mdata_in = pciu_wbm_dat_i ; +wire wbm_sm_ack_in = pciu_wbm_ack_i ; +wire wbm_sm_rty_in = pciu_wbm_rty_i ; +wire wbm_sm_err_in = pciu_wbm_err_i ; + +// WISHBONE master interface instantiation +pci_wb_master wishbone_master +( + .wb_clock_in (wb_clock_in), + .reset_in (reset_in), + .pci_tar_read_request (wbm_sm_pci_tar_read_request), //in + .pci_tar_address (wbm_sm_pci_tar_address), //in + .pci_tar_cmd (wbm_sm_pci_tar_cmd), //in + .pci_tar_be (wbm_sm_pci_tar_be), //in + .pci_tar_burst_ok (wbm_sm_pci_tar_burst_ok), //in + .pci_cache_line_size (wbm_sm_pci_cache_line_size), //in + .cache_lsize_not_zero (wbm_sm_cache_lsize_not_zero_in), + .wb_read_done_out (wbm_sm_wb_read_done), //out + .w_attempt (wbm_sm_write_attempt), //out + .pcir_fifo_wenable_out (wbm_sm_pcir_fifo_wenable_out), + .pcir_fifo_data_out (wbm_sm_pcir_fifo_data_out), + .pcir_fifo_be_out (wbm_sm_pcir_fifo_be_out), + .pcir_fifo_control_out (wbm_sm_pcir_fifo_control_out), + .pciw_fifo_renable_out (wbm_sm_pciw_fifo_renable_out), + .pciw_fifo_addr_data_in (wbm_sm_pciw_fifo_addr_data_in), + .pciw_fifo_cbe_in (wbm_sm_pciw_fifo_cbe_in), + .pciw_fifo_control_in (wbm_sm_pciw_fifo_control_in), + .pciw_fifo_almost_empty_in (wbm_sm_pciw_fifo_almost_empty_in), + .pciw_fifo_empty_in (wbm_sm_pciw_fifo_empty_in), + .pciw_fifo_transaction_ready_in (wbm_sm_pciw_fifo_transaction_ready_in), + .pci_error_sig_out (wbm_sm_pci_error_sig_out), + .pci_error_bc (wbm_sm_pci_error_bc), + .write_rty_cnt_exp_out (wbm_sm_write_rty_cnt_exp_out), + .error_source_out (wbm_sm_error_source_out), + .read_rty_cnt_exp_out (wbm_sm_read_rty_cnt_exp_out), + .wb_cyc_o (wbm_sm_cyc_out), + .wb_stb_o (wbm_sm_stb_out), + .wb_we_o (wbm_sm_we_out), + .wb_cti_o (wbm_sm_cti_out), + .wb_bte_o (wbm_sm_bte_out), + .wb_sel_o (wbm_sm_sel_out), + .wb_adr_o (wbm_sm_adr_out), + .wb_dat_i (wbm_sm_mdata_in), + .wb_dat_o (wbm_sm_mdata_out), + .wb_ack_i (wbm_sm_ack_in), + .wb_rty_i (wbm_sm_rty_in), + .wb_err_i (wbm_sm_err_in) +); + +// pciw_pcir_fifos inputs +// PCIW_FIFO inputs +wire fifos_pciw_wenable_in = pcit_if_pciw_fifo_wenable_out ; +wire [31:0] fifos_pciw_addr_data_in = pcit_if_pciw_fifo_addr_data_out ; +wire [3:0] fifos_pciw_cbe_in = pcit_if_pciw_fifo_cbe_out ; +wire [3:0] fifos_pciw_control_in = pcit_if_pciw_fifo_control_out ; +wire fifos_pciw_renable_in = wbm_sm_pciw_fifo_renable_out ; +//wire fifos_pciw_flush_in = 1'b0 ; // flush not used for write fifo + +// PCIR_FIFO inputs +wire fifos_pcir_wenable_in = wbm_sm_pcir_fifo_wenable_out ; +wire [31:0] fifos_pcir_data_in = wbm_sm_pcir_fifo_data_out ; +wire [3:0] fifos_pcir_be_in = wbm_sm_pcir_fifo_be_out ; +wire [3:0] fifos_pcir_control_in = wbm_sm_pcir_fifo_control_out ; +wire fifos_pcir_renable_in = pcit_if_pcir_fifo_renable_out ; +wire fifos_pcir_flush_in = pcit_if_pcir_fifo_flush_out ; + +// PCIW_FIFO and PCIR_FIFO instantiation +pci_pciw_pcir_fifos fifos +( + .wb_clock_in (wb_clock_in), + .pci_clock_in (pci_clock_in), + .reset_in (reset_in), + .pciw_wenable_in (fifos_pciw_wenable_in), //for PCI Target !!! + .pciw_addr_data_in (fifos_pciw_addr_data_in), //for PCI Target !!! + .pciw_cbe_in (fifos_pciw_cbe_in), //for PCI Target !!! + .pciw_control_in (fifos_pciw_control_in), //for PCI Target !!! + .pciw_renable_in (fifos_pciw_renable_in), + .pciw_addr_data_out (fifos_pciw_addr_data_out), + .pciw_cbe_out (fifos_pciw_cbe_out), + .pciw_control_out (fifos_pciw_control_out), +// .pciw_flush_in (fifos_pciw_flush_in), // flush not used for write fifo + .pciw_three_left_out (fifos_pciw_three_left_out), //for PCI Target !!! + .pciw_two_left_out (fifos_pciw_two_left_out), //for PCI Target !!! + .pciw_almost_full_out (fifos_pciw_almost_full_out), //for PCI Target !!! + .pciw_full_out (fifos_pciw_full_out), //for PCI Target !!! + .pciw_almost_empty_out (fifos_pciw_almost_empty_out), + .pciw_empty_out (fifos_pciw_empty_out), + .pciw_transaction_ready_out (fifos_pciw_transaction_ready_out), + .pcir_wenable_in (fifos_pcir_wenable_in), + .pcir_data_in (fifos_pcir_data_in), + .pcir_be_in (fifos_pcir_be_in), + .pcir_control_in (fifos_pcir_control_in), + .pcir_renable_in (fifos_pcir_renable_in), //for PCI Target !!! + .pcir_data_out (fifos_pcir_data_out), //for PCI Target !!! + .pcir_be_out (fifos_pcir_be_out), //for PCI Target !!! + .pcir_control_out (fifos_pcir_control_out), //for PCI Target !!! + .pcir_flush_in (fifos_pcir_flush_in), //for PCI Target !!! + .pcir_full_out (), + .pcir_almost_empty_out (fifos_pcir_almost_empty_out), //for PCI Target !!! + .pcir_empty_out (fifos_pcir_empty_out), //for PCI Target !!! + .pcir_transaction_ready_out () + +`ifdef PCI_BIST + , + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +) ; + +// delayed transaction logic inputs +wire del_sync_req_in = pcit_if_req_out ; +wire del_sync_comp_in = wbm_sm_wb_read_done ; +wire del_sync_done_in = pcit_if_done_out ; +wire del_sync_in_progress_in = pcit_if_in_progress_out ; +wire [31:0] del_sync_addr_in = pcit_if_addr_out ; +wire [3:0] del_sync_be_in = pcit_if_be_out ; +wire del_sync_we_in = pcit_if_we_out ; +wire [3:0] del_sync_bc_in = pcit_if_bc_out ; +wire del_sync_status_in = 1'b0 ; +wire del_sync_burst_in = pcit_if_burst_ok_out ; +wire del_sync_retry_expired_in = wbm_sm_read_rty_cnt_exp_out ; + +// delayed transaction logic instantiation +pci_delayed_sync del_sync +( + .reset_in (reset_in), + .req_clk_in (pci_clock_in), + .comp_clk_in (wb_clock_in), + .req_in (del_sync_req_in), + .comp_in (del_sync_comp_in), + .done_in (del_sync_done_in), + .in_progress_in (del_sync_in_progress_in), + .comp_req_pending_out (del_sync_comp_req_pending_out), + .comp_comp_pending_out (del_sync_comp_comp_pending_out), + .req_req_pending_out (del_sync_req_req_pending_out), + .req_comp_pending_out (del_sync_req_comp_pending_out), + .addr_in (del_sync_addr_in), + .be_in (del_sync_be_in), + .addr_out (del_sync_addr_out), + .be_out (del_sync_be_out), + .we_in (del_sync_we_in), + .we_out (del_sync_we_out), + .bc_in (del_sync_bc_in), + .bc_out (del_sync_bc_out), + .status_in (del_sync_status_in), + .status_out (del_sync_status_out), + .comp_flush_out (del_sync_comp_flush_out), + .burst_in (del_sync_burst_in), + .burst_out (del_sync_burst_out), + .retry_expired_in (del_sync_retry_expired_in) +); + +// pci target interface inputs +wire [31:0] pcit_if_address_in = pcit_sm_address_out ; +wire [3:0] pcit_if_bc_in = pcit_sm_bc_out ; +wire pcit_if_bc0_in = pcit_sm_bc0_out ; +wire [31:0] pcit_if_data_in = pcit_sm_data_out ; +wire [3:0] pcit_if_be_in = pcit_sm_be_out ; +wire [3:0] pcit_if_next_be_in = pcit_sm_next_be_out ; +wire pcit_if_req_in = pcit_sm_req_out ; +wire pcit_if_rdy_in = pcit_sm_rdy_out ; +wire pcit_if_addr_phase_in = pcit_sm_addr_phase_out ; +wire pcit_if_bckp_devsel_in = pcit_sm_bckp_devsel_out ; +wire pcit_if_bckp_trdy_in = pcit_sm_bckp_trdy_out ; +wire pcit_if_bckp_stop_in = pcit_sm_bckp_stop_out ; +wire pcit_if_last_reg_in = pcit_sm_last_reg_out ; +wire pcit_if_frame_reg_in = pcit_sm_frame_reg_out ; +wire pcit_if_fetch_pcir_fifo_in = pcit_sm_fetch_pcir_fifo_out ; +wire pcit_if_load_medium_reg_in = pcit_sm_load_medium_reg_out ; +wire pcit_if_sel_fifo_mreg_in = pcit_sm_sel_fifo_mreg_out ; +wire pcit_if_sel_conf_fifo_in = pcit_sm_sel_conf_fifo_out ; +wire pcit_if_load_to_pciw_fifo_in = pcit_sm_load_to_pciw_fifo_out ; +wire pcit_if_load_to_conf_in = pcit_sm_load_to_conf_out ; +wire pcit_if_req_req_pending_in = del_sync_req_req_pending_out ; +wire pcit_if_req_comp_pending_in = del_sync_req_comp_pending_out ; +wire pcit_if_status_in = del_sync_status_out ; +wire [31:0] pcit_if_strd_addr_in = del_sync_addr_out ; +wire [3:0] pcit_if_strd_bc_in = del_sync_bc_out ; +wire pcit_if_comp_flush_in = del_sync_comp_flush_out ; +wire [31:0] pcit_if_pcir_fifo_data_in = fifos_pcir_data_out ; +wire [3:0] pcit_if_pcir_fifo_be_in = fifos_pcir_be_out ; +wire [3:0] pcit_if_pcir_fifo_control_in = fifos_pcir_control_out ; +wire pcit_if_pcir_fifo_almost_empty_in = fifos_pcir_almost_empty_out ; +wire pcit_if_pcir_fifo_empty_in = fifos_pcir_empty_out ; +wire pcit_if_pciw_fifo_three_left_in = fifos_pciw_three_left_out ; +wire pcit_if_pciw_fifo_two_left_in = fifos_pciw_two_left_out ; +wire pcit_if_pciw_fifo_almost_full_in = fifos_pciw_almost_full_out ; +wire pcit_if_pciw_fifo_full_in = fifos_pciw_full_out ; +wire pcit_if_wbw_fifo_empty_in = pciu_wbw_fifo_empty_in ; +wire pcit_if_wbu_del_read_comp_pending_in = pciu_wbu_del_read_comp_pending_in ; +wire [31:0] pcit_if_conf_data_in = pciu_conf_data_in ; +wire pcit_if_mem_enable_in = pciu_mem_enable_in ; +wire pcit_if_io_enable_in = pciu_io_enable_in ; +wire pcit_if_mem_io_addr_space0_in = pciu_map_in[0] ; +wire pcit_if_mem_io_addr_space1_in = pciu_map_in[1] ; +wire pcit_if_mem_io_addr_space2_in = pciu_map_in[2] ; +wire pcit_if_mem_io_addr_space3_in = pciu_map_in[3] ; +wire pcit_if_mem_io_addr_space4_in = pciu_map_in[4] ; +wire pcit_if_mem_io_addr_space5_in = pciu_map_in[5] ; +wire pcit_if_pre_fetch_en0_in = pciu_pref_en_in[0] ; +wire pcit_if_pre_fetch_en1_in = pciu_pref_en_in[1] ; +wire pcit_if_pre_fetch_en2_in = pciu_pref_en_in[2] ; +wire pcit_if_pre_fetch_en3_in = pciu_pref_en_in[3] ; +wire pcit_if_pre_fetch_en4_in = pciu_pref_en_in[4] ; +wire pcit_if_pre_fetch_en5_in = pciu_pref_en_in[5] ; +wire [(pci_ba0_width - 1):0] pcit_if_pci_base_addr0_in = pciu_bar0_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_base_addr1_in = pciu_bar1_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_base_addr2_in = pciu_bar2_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_base_addr3_in = pciu_bar3_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_base_addr4_in = pciu_bar4_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_base_addr5_in = pciu_bar5_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask0_in = pciu_am0_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask1_in = pciu_am1_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask2_in = pciu_am2_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask3_in = pciu_am3_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask4_in = pciu_am4_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_addr_mask5_in = pciu_am5_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr0_in = pciu_ta0_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr1_in = pciu_ta1_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr2_in = pciu_ta2_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr3_in = pciu_ta3_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr4_in = pciu_ta4_in ; +wire [(pci_ba1_5_width - 1):0] pcit_if_pci_tran_addr5_in = pciu_ta5_in ; +wire pcit_if_addr_tran_en0_in = pciu_at_en_in[0] ; +wire pcit_if_addr_tran_en1_in = pciu_at_en_in[1] ; +wire pcit_if_addr_tran_en2_in = pciu_at_en_in[2] ; +wire pcit_if_addr_tran_en3_in = pciu_at_en_in[3] ; +wire pcit_if_addr_tran_en4_in = pciu_at_en_in[4] ; +wire pcit_if_addr_tran_en5_in = pciu_at_en_in[5] ; + +pci_target32_interface pci_target_if +( + .clk_in (pci_clock_in), + .reset_in (reset_in), + .address_in (pcit_if_address_in), + .addr_claim_out (pcit_if_addr_claim_out), + .bc_in (pcit_if_bc_in), + .bc0_in (pcit_if_bc0_in), + .data_in (pcit_if_data_in), + .data_out (pcit_if_data_out), + .be_in (pcit_if_be_in), + .next_be_in (pcit_if_next_be_in), + .req_in (pcit_if_req_in), + .rdy_in (pcit_if_rdy_in), + .addr_phase_in (pcit_if_addr_phase_in), + .bckp_devsel_in (pcit_if_bckp_devsel_in), + .bckp_trdy_in (pcit_if_bckp_trdy_in), + .bckp_stop_in (pcit_if_bckp_stop_in), + .last_reg_in (pcit_if_last_reg_in), + .frame_reg_in (pcit_if_frame_reg_in), + .fetch_pcir_fifo_in (pcit_if_fetch_pcir_fifo_in), + .load_medium_reg_in (pcit_if_load_medium_reg_in), + .sel_fifo_mreg_in (pcit_if_sel_fifo_mreg_in), + .sel_conf_fifo_in (pcit_if_sel_conf_fifo_in), + .load_to_pciw_fifo_in (pcit_if_load_to_pciw_fifo_in), + .load_to_conf_in (pcit_if_load_to_conf_in), + .same_read_out (pcit_if_same_read_out), + .norm_access_to_config_out (pcit_if_norm_access_to_config_out), + .read_completed_out (pcit_if_read_completed_out), + .read_processing_out (pcit_if_read_processing_out), + .target_abort_out (pcit_if_target_abort_out), + .disconect_wo_data_out (pcit_if_disconect_wo_data_out), + .disconect_w_data_out (pcit_if_disconect_w_data_out), + .pciw_fifo_full_out (pcit_if_pciw_fifo_full_out), + .pcir_fifo_data_err_out (pcit_if_pcir_fifo_data_err_out), + .wbw_fifo_empty_out (pcit_if_wbw_fifo_empty_out), + .wbu_del_read_comp_pending_out (pcit_if_wbu_del_read_comp_pending_out), + .req_out (pcit_if_req_out), + .done_out (pcit_if_done_out), + .in_progress_out (pcit_if_in_progress_out), + .req_req_pending_in (pcit_if_req_req_pending_in), + .req_comp_pending_in (pcit_if_req_comp_pending_in), + .addr_out (pcit_if_addr_out), + .be_out (pcit_if_be_out), + .we_out (pcit_if_we_out), + .bc_out (pcit_if_bc_out), + .burst_ok_out (pcit_if_burst_ok_out), + .strd_addr_in (pcit_if_strd_addr_in), + .strd_bc_in (pcit_if_strd_bc_in), + .status_in (pcit_if_status_in), + .comp_flush_in (pcit_if_comp_flush_in), + .pcir_fifo_renable_out (pcit_if_pcir_fifo_renable_out), + .pcir_fifo_data_in (pcit_if_pcir_fifo_data_in), + .pcir_fifo_be_in (pcit_if_pcir_fifo_be_in), + .pcir_fifo_control_in (pcit_if_pcir_fifo_control_in), + .pcir_fifo_flush_out (pcit_if_pcir_fifo_flush_out), + .pcir_fifo_almost_empty_in (pcit_if_pcir_fifo_almost_empty_in), + .pcir_fifo_empty_in (pcit_if_pcir_fifo_empty_in), + .pciw_fifo_wenable_out (pcit_if_pciw_fifo_wenable_out), + .pciw_fifo_addr_data_out (pcit_if_pciw_fifo_addr_data_out), + .pciw_fifo_cbe_out (pcit_if_pciw_fifo_cbe_out), + .pciw_fifo_control_out (pcit_if_pciw_fifo_control_out), + .pciw_fifo_three_left_in (pcit_if_pciw_fifo_three_left_in), + .pciw_fifo_two_left_in (pcit_if_pciw_fifo_two_left_in), + .pciw_fifo_almost_full_in (pcit_if_pciw_fifo_almost_full_in), + .pciw_fifo_full_in (pcit_if_pciw_fifo_full_in), + .wbw_fifo_empty_in (pcit_if_wbw_fifo_empty_in), + .wbu_del_read_comp_pending_in (pcit_if_wbu_del_read_comp_pending_in), + .conf_addr_out (pcit_if_conf_addr_out), + .conf_data_out (pcit_if_conf_data_out), + .conf_data_in (pcit_if_conf_data_in), + .conf_be_out (pcit_if_conf_be_out), + .conf_we_out (pcit_if_conf_we_out), + .conf_re_out (pcit_if_conf_re_out), + .mem_enable_in (pcit_if_mem_enable_in), + .io_enable_in (pcit_if_io_enable_in), + .mem_io_addr_space0_in (pcit_if_mem_io_addr_space0_in), + .mem_io_addr_space1_in (pcit_if_mem_io_addr_space1_in), + .mem_io_addr_space2_in (pcit_if_mem_io_addr_space2_in), + .mem_io_addr_space3_in (pcit_if_mem_io_addr_space3_in), + .mem_io_addr_space4_in (pcit_if_mem_io_addr_space4_in), + .mem_io_addr_space5_in (pcit_if_mem_io_addr_space5_in), + .pre_fetch_en0_in (pcit_if_pre_fetch_en0_in), + .pre_fetch_en1_in (pcit_if_pre_fetch_en1_in), + .pre_fetch_en2_in (pcit_if_pre_fetch_en2_in), + .pre_fetch_en3_in (pcit_if_pre_fetch_en3_in), + .pre_fetch_en4_in (pcit_if_pre_fetch_en4_in), + .pre_fetch_en5_in (pcit_if_pre_fetch_en5_in), + .pci_base_addr0_in (pcit_if_pci_base_addr0_in), + .pci_base_addr1_in (pcit_if_pci_base_addr1_in), + .pci_base_addr2_in (pcit_if_pci_base_addr2_in), + .pci_base_addr3_in (pcit_if_pci_base_addr3_in), + .pci_base_addr4_in (pcit_if_pci_base_addr4_in), + .pci_base_addr5_in (pcit_if_pci_base_addr5_in), + .pci_addr_mask0_in (pcit_if_pci_addr_mask0_in), + .pci_addr_mask1_in (pcit_if_pci_addr_mask1_in), + .pci_addr_mask2_in (pcit_if_pci_addr_mask2_in), + .pci_addr_mask3_in (pcit_if_pci_addr_mask3_in), + .pci_addr_mask4_in (pcit_if_pci_addr_mask4_in), + .pci_addr_mask5_in (pcit_if_pci_addr_mask5_in), + .pci_tran_addr0_in (pcit_if_pci_tran_addr0_in), + .pci_tran_addr1_in (pcit_if_pci_tran_addr1_in), + .pci_tran_addr2_in (pcit_if_pci_tran_addr2_in), + .pci_tran_addr3_in (pcit_if_pci_tran_addr3_in), + .pci_tran_addr4_in (pcit_if_pci_tran_addr4_in), + .pci_tran_addr5_in (pcit_if_pci_tran_addr5_in), + .addr_tran_en0_in (pcit_if_addr_tran_en0_in), + .addr_tran_en1_in (pcit_if_addr_tran_en1_in), + .addr_tran_en2_in (pcit_if_addr_tran_en2_in), + .addr_tran_en3_in (pcit_if_addr_tran_en3_in), + .addr_tran_en4_in (pcit_if_addr_tran_en4_in), + .addr_tran_en5_in (pcit_if_addr_tran_en5_in) +) ; + +// pci target state machine inputs +wire pcit_sm_frame_in = pciu_pciif_frame_in ; +wire pcit_sm_irdy_in = pciu_pciif_irdy_in ; +wire pcit_sm_idsel_in = pciu_pciif_idsel_in ; +wire pcit_sm_frame_reg_in = pciu_pciif_frame_reg_in ; +wire pcit_sm_irdy_reg_in = pciu_pciif_irdy_reg_in ; +wire pcit_sm_idsel_reg_in = pciu_pciif_idsel_reg_in ; +wire [31:0] pcit_sm_ad_reg_in = pciu_pciif_ad_reg_in ; +wire [3:0] pcit_sm_cbe_reg_in = pciu_pciif_cbe_reg_in ; +wire [3:0] pcit_sm_cbe_in = pciu_pciif_cbe_in ; +wire pcit_sm_bckp_trdy_en_in = pciu_pciif_bckp_trdy_en_in ; +wire pcit_sm_bckp_devsel_in = pciu_pciif_bckp_devsel_in ; +wire pcit_sm_bckp_trdy_in = pciu_pciif_bckp_trdy_in ; +wire pcit_sm_bckp_stop_in = pciu_pciif_bckp_stop_in ; +wire pcit_sm_addr_claim_in = pcit_if_addr_claim_out ; +wire [31:0] pcit_sm_data_in = pcit_if_data_out ; +wire pcit_sm_same_read_in = pcit_if_same_read_out ; +wire pcit_sm_norm_access_to_config_in = pcit_if_norm_access_to_config_out ; +wire pcit_sm_read_completed_in = pcit_if_read_completed_out ; +wire pcit_sm_read_processing_in = pcit_if_read_processing_out ; +wire pcit_sm_target_abort_in = pcit_if_target_abort_out ; +wire pcit_sm_disconect_wo_data_in = pcit_if_disconect_wo_data_out ; +wire pcit_sm_disconect_w_data_in = pcit_if_disconect_w_data_out ; +wire pcit_sm_pciw_fifo_full_in = pcit_if_pciw_fifo_full_out ; +wire pcit_sm_pcir_fifo_data_err_in = pcit_if_pcir_fifo_data_err_out ; +wire pcit_sm_wbw_fifo_empty_in = pcit_if_wbw_fifo_empty_out ; +wire pcit_sm_wbu_del_read_comp_pending_in = pcit_if_wbu_del_read_comp_pending_out ; +wire pcit_sm_wbu_frame_en_in = pciu_wbu_frame_en_in ; +wire pcit_sm_trdy_reg_in = pciu_pciif_trdy_reg_in ; +wire pcit_sm_stop_reg_in = pciu_pciif_stop_reg_in ; + + +pci_target32_sm pci_target_sm +( + .clk_in (pci_clock_in), + .reset_in (reset_in), + .pci_frame_in (pcit_sm_frame_in), + .pci_irdy_in (pcit_sm_irdy_in), + .pci_idsel_in (pcit_sm_idsel_in), + .pci_frame_reg_in (pcit_sm_frame_reg_in), + .pci_irdy_reg_in (pcit_sm_irdy_reg_in), + .pci_idsel_reg_in (pcit_sm_idsel_reg_in), + .pci_trdy_out (pcit_sm_trdy_out), + .pci_stop_out (pcit_sm_stop_out), + .pci_devsel_out (pcit_sm_devsel_out), + .pci_trdy_en_out (pcit_sm_trdy_en_out), + .pci_stop_en_out (pcit_sm_stop_en_out), + .pci_devsel_en_out (pcit_sm_devsel_en_out), + .ad_load_out (pcit_sm_ad_load_out), + .ad_load_on_transfer_out (pcit_sm_ad_load_on_transfer_out), + .pci_ad_reg_in (pcit_sm_ad_reg_in), + .pci_ad_out (pcit_sm_ad_out), + .pci_ad_en_out (pcit_sm_ad_en_out), + .pci_cbe_reg_in (pcit_sm_cbe_reg_in), + .pci_cbe_in (pcit_sm_cbe_in), + .bckp_trdy_en_in (pcit_sm_bckp_trdy_en_in), + .bckp_devsel_in (pcit_sm_bckp_devsel_in), + .bckp_trdy_in (pcit_sm_bckp_trdy_in), + .bckp_stop_in (pcit_sm_bckp_stop_in), + .pci_trdy_reg_in (pcit_sm_trdy_reg_in), + .pci_stop_reg_in (pcit_sm_stop_reg_in), + .address_out (pcit_sm_address_out), + .addr_claim_in (pcit_sm_addr_claim_in), + .bc_out (pcit_sm_bc_out), + .bc0_out (pcit_sm_bc0_out), + .data_out (pcit_sm_data_out), + .data_in (pcit_sm_data_in), + .be_out (pcit_sm_be_out), + .next_be_out (pcit_sm_next_be_out), + .req_out (pcit_sm_req_out), + .rdy_out (pcit_sm_rdy_out), + .addr_phase_out (pcit_sm_addr_phase_out), + .bckp_devsel_out (pcit_sm_bckp_devsel_out), + .bckp_trdy_out (pcit_sm_bckp_trdy_out), + .bckp_stop_out (pcit_sm_bckp_stop_out), + .last_reg_out (pcit_sm_last_reg_out), + .frame_reg_out (pcit_sm_frame_reg_out), + .fetch_pcir_fifo_out (pcit_sm_fetch_pcir_fifo_out), + .load_medium_reg_out (pcit_sm_load_medium_reg_out), + .sel_fifo_mreg_out (pcit_sm_sel_fifo_mreg_out), + .sel_conf_fifo_out (pcit_sm_sel_conf_fifo_out), + .load_to_pciw_fifo_out (pcit_sm_load_to_pciw_fifo_out), + .load_to_conf_out (pcit_sm_load_to_conf_out), + .same_read_in (pcit_sm_same_read_in), + .norm_access_to_config_in (pcit_sm_norm_access_to_config_in), + .read_completed_in (pcit_sm_read_completed_in), + .read_processing_in (pcit_sm_read_processing_in), + .target_abort_in (pcit_sm_target_abort_in), + .disconect_wo_data_in (pcit_sm_disconect_wo_data_in), + .disconect_w_data_in (pcit_sm_disconect_w_data_in), + .target_abort_set_out (pcit_sm_target_abort_set_out), + .pciw_fifo_full_in (pcit_sm_pciw_fifo_full_in), + .pcir_fifo_data_err_in (pcit_sm_pcir_fifo_data_err_in), + .wbw_fifo_empty_in (pcit_sm_wbw_fifo_empty_in), + .wbu_del_read_comp_pending_in (pcit_sm_wbu_del_read_comp_pending_in), + .wbu_frame_en_in (pcit_sm_wbu_frame_en_in) +) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v new file mode 100644 index 000000000..f65ffec42 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v @@ -0,0 +1,330 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "pci_user_constants.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// - Tadej Markovic (tadej@opencores.org) //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_user_constants.v,v $ +// Revision 1.15 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.14 2004/07/07 12:45:01 mihad +// Added SubsystemVendorID, SubsystemID, MAXLatency, MinGnt defines. +// Enabled value loading from serial EEPROM for all of the above + VendorID and DeviceID registers. +// +// Revision 1.13 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.12 2003/12/28 09:54:48 fr2201 +// def_wb_imagex_addr_map defined correctly +// +// Revision 1.11 2003/12/28 09:20:00 fr2201 +// Reset values for PCI, WB defined (PCI_TAx,WB_BAx,WB_TAx,WB_AMx,WB_BAx_MEM_IO) +// +// Revision 1.10 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.9 2003/08/03 18:05:06 mihad +// Added limited WISHBONE B3 support for WISHBONE Slave Unit. +// Doesn't support full speed bursts yet. +// +// Revision 1.8 2003/03/14 15:31:57 mihad +// Entered the option to disable no response counter in wb master. +// +// Revision 1.7 2003/01/27 17:05:50 mihad +// Updated. +// +// Revision 1.6 2003/01/27 16:51:19 mihad +// Old files with wrong names removed. +// +// Revision 1.5 2003/01/21 16:06:56 mihad +// Bug fixes, testcases added. +// +// Revision 1.4 2002/09/30 17:22:45 mihad +// Added support for Virtual Silicon two port RAM. Didn't run regression on it yet! +// +// Revision 1.3 2002/08/13 11:03:53 mihad +// Added a few testcases. Repaired wrong reset value for PCI_AM5 register. Repaired Parity Error Detected bit setting. Changed PCI_AM0 to always enabled(regardles of PCI_AM0 define), if image 0 is used as configuration image +// +// Revision 1.2 2002/03/05 11:53:47 mihad +// Added some testcases, removed un-needed fifo signals +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// + +// Fifo implementation defines: +// If FPGA and XILINX are defined, Xilinx's BlockSelectRAM+ is instantiated for Fifo storage. +// 16 bit width is used, so 8 bits of address ( 256 ) locations are available. If RAM_DONT_SHARE is not defined (commented out), +// then one block RAM is shared between two FIFOs. That means each Fifo can have a maximum address length of 7 - depth of 128 and only 6 block rams are used +// If RAM_DONT_SHARE is defined ( not commented out ), then 12 block RAMs are used and each Fifo can have a maximum address length of 8 ( 256 locations ) +// If FPGA is not defined, then ASIC RAMs are used. Currently there is only one version of ARTISAN RAM supported. User should generate synchronous RAM with +// width of 40 and instantiate it in pci_tpram.v. If RAM_DONT_SHARE is defined, then these can be dual port rams ( write port +// in one clock domain, read in other ), otherwise it must be two port RAM ( read and write ports in both clock domains ). +// If RAM_DONT_SHARE is defined, then all RAM address lengths must be specified accordingly, otherwise there are two relevant lengths - PCI_FIFO_RAM_ADDR_LENGTH and +// WB_FIFO_RAM_ADDR_LENGTH. + +`define WBW_ADDR_LENGTH 4 +`define WBR_ADDR_LENGTH 4 +`define PCIW_ADDR_LENGTH 3 +`define PCIR_ADDR_LENGTH 3 + +//`define FPGA +//`define XILINX + +`define WB_RAM_DONT_SHARE +`define PCI_RAM_DONT_SHARE + +`ifdef FPGA + `ifdef XILINX + `define PCI_FIFO_RAM_ADDR_LENGTH 8 // PCI target unit fifo storage definition + `define WB_FIFO_RAM_ADDR_LENGTH 8 // WB slave unit fifo storage definition + `define PCI_XILINX_RAMB4 + `define WB_XILINX_RAMB4 + //`define PCI_XILINX_DIST_RAM + //`define WB_XILINX_DIST_RAM + `endif +`else + `define PCI_FIFO_RAM_ADDR_LENGTH 3 // PCI target unit fifo storage definition when RAM sharing is used ( both pcir and pciw fifo use same instance of RAM ) + `define WB_FIFO_RAM_ADDR_LENGTH 4 // WB slave unit fifo storage definition when RAM sharing is used ( both wbr and wbw fifo use same instance of RAM ) +// `define WB_ARTISAN_SDP +// `define PCI_ARTISAN_SDP +// `define PCI_VS_STP +// `define WB_VS_STP +`endif + +// these two defines allow user to select active high or low output enables on PCI bus signals, depending on +// output buffers instantiated. Xilinx FPGAs use active low output enables. +`define ACTIVE_LOW_OE +//`define ACTIVE_HIGH_OE + +// HOST/GUEST implementation selection - see design document and specification for description of each implementation +// only one can be defined at same time +//`define HOST +`define GUEST + +// if NO_CNF_IMAGE is commented out, then READ-ONLY access to configuration space is ENABLED: +// - ENABLED Read-Only access from WISHBONE for GUEST bridges +// - ENABLED Read-Only access from PCI for HOST bridges +// with defining NO_CNF_IMAGE, one decoder and one multiplexer are saved +`define NO_CNF_IMAGE + +// number defined here specifies how many MS bits in PCI address are compared with base address, to decode +// accesses. Maximum number allows for minimum image size ( number = 20, image size = 4KB ), minimum number +// allows for maximum image size ( number = 1, image size = 2GB ). If you intend on using different sizes of PCI images, +// you have to define a number of minimum sized image and enlarge others by specifying different address mask. +// smaller the number here, faster the decoder operation +`define PCI_NUM_OF_DEC_ADDR_LINES 24 + +// no. of PCI Target IMAGES +// - PCI provides 6 base address registers for image implementation. +// PCI_IMAGE1 definition is not required and has no effect, since PCI image 1 is always implemented +// If GUEST is defined, PCI Image 0 is also always implemented and is used for configuration space +// access. +// If HOST is defined and NO_CNF_IMAGE is not, then PCI Image 0 is used for Read Only access to configuration +// space. If HOST is defined and NO_CNF_IMAGE is defined, then user can define PCI_IMAGE0 as normal image, and there +// is no access to Configuration space possible from PCI bus. +// Implementation of all other PCI images is selected by defining PCI_IMAGE2 through PCI_IMAGE5 regardles of HOST +// or GUEST implementation. +`ifdef HOST + `ifdef NO_CNF_IMAGE + //`define PCI_IMAGE0 + `endif +`endif + +//`define PCI_IMAGE2 +//`define PCI_IMAGE3 +//`define PCI_IMAGE4 +//`define PCI_IMAGE5 + +// initial value for PCI image address masks. Address masks can be defined in enabled state, +// to allow device independent software to detect size of image and map base addresses to +// memory space. If initial mask for an image is defined as 0, then device independent software +// won't detect base address implemented and device dependent software will have to configure +// address masks as well as base addresses! +// Don't define PCI_AMx to 24'hffff_ff for memory images! Use that just for I/O images. +`define PCI_AM0 24'hffff_f0 +`define PCI_AM1 24'hffff_ff +`define PCI_AM2 24'hffff_f0 +`define PCI_AM3 24'hffff_f0 +`define PCI_AM4 24'hffff_f0 +`define PCI_AM5 24'hffff_f0 + +// initial value for PCI image maping to MEMORY or IO spaces. If initial define is set to 0, +// then IMAGE with that base address points to MEMORY space, othervise it points ti IO space. D +// Device independent software sets the base addresses acording to MEMORY or IO maping! +`define PCI_BA0_MEM_IO 1'b0 // considered only when PCI_IMAGE0 is used as general PCI-WB image! +`define PCI_BA1_MEM_IO 1'b1 +`define PCI_BA2_MEM_IO 1'b0 +`define PCI_BA3_MEM_IO 1'b0 +`define PCI_BA4_MEM_IO 1'b0 +`define PCI_BA5_MEM_IO 1'b0 + +// initial value for PCI translation addresses. The initial values +// are set after reset. When ADDR_TRAN_IMPL is defined then then Images +// are transleted to this adresses whithout access to pci_ta registers. +`define PCI_TA0 24'h0000_0 +`define PCI_TA1 24'h0000_0 +`define PCI_TA2 24'h0000_0 +`define PCI_TA3 24'h0000_0 +`define PCI_TA4 24'h0000_0 +`define PCI_TA5 24'h0000_0 + +`define PCI_AT_EN0 1'b0 +`define PCI_AT_EN1 1'b0 +`define PCI_AT_EN2 1'b0 +`define PCI_AT_EN3 1'b0 +`define PCI_AT_EN4 1'b0 +`define PCI_AT_EN5 1'b0 + +// number defined here specifies how many MS bits in WB address are compared with base address, to decode +// accesses. Maximum number allows for minimum image size ( number = 20, image size = 4KB ), minimum number +// allows for maximum image size ( number = 1, image size = 2GB ). If you intend on using different sizes of WB images, +// you have to define a number of minimum sized image and enlarge others by specifying different address mask. +// smaller the number here, faster the decoder operation +`define WB_NUM_OF_DEC_ADDR_LINES 1 + +// no. of WISHBONE Slave IMAGES +// WB image 0 is always used for access to configuration space. In case configuration space access is not implemented, +// ( both GUEST and NO_CNF_IMAGE defined ), then WB image 0 is not implemented. User doesn't need to define image 0. +// WB Image 1 is always implemented and user doesnt need to specify its definition +// WB images' 2 through 5 implementation by defining each one. +`define WB_IMAGE2 +//`define WB_IMAGE3 +//`define WB_IMAGE4 +//`define WB_IMAGE5 + +//Address bar register defines the base address for each image. +//To asccess bus without Software configuration. +`define WB_BA1 20'h0000_0 +`define WB_BA2 20'h8000_0 +`define WB_BA3 20'h0000_0 +`define WB_BA4 20'h0000_0 +`define WB_BA5 20'h0000_0 + +// initial value for WB image maping to MEMORY or IO spaces. If initial define is set to 0, +// then IMAGE with that base address points to MEMORY space, othervise it points ti IO space. +`define WB_BA1_MEM_IO 1'b0 +`define WB_BA2_MEM_IO 1'b0 +`define WB_BA3_MEM_IO 1'b0 +`define WB_BA4_MEM_IO 1'b0 +`define WB_BA5_MEM_IO 1'b0 + +// initial value for WB image address masks. +`define WB_AM1 20'h8000_0 +`define WB_AM2 20'h8000_0 +`define WB_AM3 20'h0000_0 +`define WB_AM4 20'h0000_0 +`define WB_AM5 20'h0000_0 + +// initial value for WB translation addresses. The initial values +// are set after reset. When ADDR_TRAN_IMPL is defined then then Images +// are transleted to this adresses whithout access to pci_ta registers. +`define WB_TA1 20'h0000_0 +`define WB_TA2 20'h0000_0 +`define WB_TA3 20'h0000_0 +`define WB_TA4 20'h0000_0 +`define WB_TA5 20'h0000_0 + +`define WB_AT_EN1 1'b0 +`define WB_AT_EN2 1'b0 +`define WB_AT_EN3 1'b0 +`define WB_AT_EN4 1'b0 +`define WB_AT_EN5 1'b0 + +// If this define is commented out, then address translation will not be implemented. +// addresses will pass through bridge unchanged, regardles of address translation enable bits. +// Address translation also slows down the decoding +//When ADDR_TRAN_IMPL this define is present then adress translation is enabled after reset. +//`define ADDR_TRAN_IMPL + +// decode speed for WISHBONE definition - initial cycle on WISHBONE bus will take 1 WS for FAST, 2 WSs for MEDIUM and 3 WSs for slow. +// slower decode speed can be used, to provide enough time for address to be decoded. +`define WB_DECODE_FAST +//`define WB_DECODE_MEDIUM +//`define WB_DECODE_SLOW + +// Base address for Configuration space access from WB bus. This value cannot be changed during runtime +`define WB_CONFIGURATION_BASE 20'h0000_0 + +// Turn registered WISHBONE slave outputs on or off +// all outputs from WB Slave state machine are registered, if this is defined - WB bus outputs as well as +// outputs to internals of the core. +//`define REGISTER_WBS_OUTPUTS + +/*----------------------------------------------------------------------------------------------------------- +Core speed definition - used for simulation and 66MHz Capable bit value in status register indicating 66MHz +capable device +-----------------------------------------------------------------------------------------------------------*/ +`define PCI33 +//`define PCI66 + +/*----------------------------------------------------------------------------------------------------------- +[000h-00Ch] First 4 DWORDs (32-bit) of PCI configuration header - the same regardless of the HEADER type ! + Vendor_ID is an ID for a specific vendor defined by PCI_SIG - 2321h does not belong to anyone (e.g. + Xilinx's Vendor_ID is 10EEh and Altera's Vendor_ID is 1172h). Device_ID and Revision_ID should be used + together by application. +-----------------------------------------------------------------------------------------------------------*/ +`define HEADER_VENDOR_ID 16'h1895 +`define HEADER_DEVICE_ID 16'h0001 +`define HEADER_REVISION_ID 8'h01 +`define HEADER_SUBSYS_VENDOR_ID 16'h1895 +`define HEADER_SUBSYS_ID 16'h0001 +`define HEADER_MAX_LAT 8'h1a +`define HEADER_MIN_GNT 8'h08 + +// MAX Retry counter value for WISHBONE Master state-machine +// This value is 8-bit because of 8-bit retry counter !!! +`define WB_RTY_CNT_MAX 8'hff + +// define the macro below to disable internal retry generation in the wishbone master interface +// used when wb master accesses extremly slow devices. +`define PCI_WBM_NO_RESPONSE_CNT_DISABLE + +`define PCI_WB_REV_B3 +//`define PCI_WBS_B3_RTY_DISABLE + +`ifdef GUEST +// `define PCI_CPCI_HS_IMPLEMENT +// `define PCI_SPOCI +`endif + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v new file mode 100644 index 000000000..b35ee37f3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v @@ -0,0 +1,279 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "wb_addr_mux.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_addr_mux.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.4 2002/08/19 16:54:25 mihad +// Got rid of undef directives +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +// module provides instantiation of address decoders and address multiplexer for various number of implemented wishbone images +`include "pci_constants.v" +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_wb_addr_mux +( + `ifdef REGISTER_WBS_OUTPUTS + clk_in, + reset_in, + sample_address_in, + `endif + address_in, + bar0_in, + bar1_in, + bar2_in, + bar3_in, + bar4_in, + bar5_in, + am0_in, + am1_in, + am2_in, + am3_in, + am4_in, + am5_in, + ta0_in, + ta1_in, + ta2_in, + ta3_in, + ta4_in, + ta5_in, + at_en_in, + hit_out, + address_out +); + +input [31:0] address_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] bar5_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] am5_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] ta5_in ; +input [5:0] at_en_in ; +output [5:0] hit_out ; +output [31:0] address_out ; +reg [31:0] address_out ; + +wire [31:0] addr0 ; +wire [31:0] addr1 ; +wire [31:0] addr2 ; +wire [31:0] addr3 ; +wire [31:0] addr4 ; +wire [31:0] addr5 ; + +wire [5:0] hit ; +assign hit_out = hit ; + +`ifdef REGISTER_WBS_OUTPUTS + input clk_in, reset_in, sample_address_in ; + + reg [31:0] address ; + always@(posedge clk_in or posedge reset_in) + begin + if ( reset_in ) + address <= #`FF_DELAY 0 ; + else + if ( sample_address_in ) + address <= #`FF_DELAY address_in ; + end +`else + wire [31:0] address = address_in ; +`endif + +`ifdef GUEST + `ifdef NO_CNF_IMAGE + `else + `define PCI_WB_ADDR_MUX_DEC0_INCLUDE + `endif +`else +`ifdef HOST + `define PCI_WB_ADDR_MUX_DEC0_INCLUDE +`endif +`endif + +`ifdef PCI_WB_ADDR_MUX_DEC0_INCLUDE + pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec0 + ( + .hit (hit[0]), + .addr_out (addr0), + .addr_in (address), + .base_addr (bar0_in), + .mask_addr (am0_in), + .tran_addr (ta0_in), + .at_en (1'b0) + ) ; +`else + // configuration image not implemented + assign hit[0] = 1'b0 ; + assign addr0 = 32'h0000_0000 ; +`endif + +// one image is always implemented +pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec1 +( + .hit (hit[1]), + .addr_out (addr1), + .addr_in (address), + .base_addr (bar1_in), + .mask_addr (am1_in), + .tran_addr (ta1_in), + .at_en (at_en_in[1]) +) ; + +`ifdef WB_IMAGE2 + pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec2 + ( + .hit (hit[2]), + .addr_out (addr2), + .addr_in (address), + .base_addr (bar2_in), + .mask_addr (am2_in), + .tran_addr (ta2_in), + .at_en (at_en_in[2]) + ) ; + +`else + assign hit[2] = 1'b0 ; + assign addr2 = 0 ; +`endif + +`ifdef WB_IMAGE3 + pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec3 + ( + .hit (hit[3]), + .addr_out (addr3), + .addr_in (address), + .base_addr (bar3_in), + .mask_addr (am3_in), + .tran_addr (ta3_in), + .at_en (at_en_in[3]) + ) ; +`else + assign hit[3] = 1'b0 ; + assign addr3 = 0 ; +`endif + +`ifdef WB_IMAGE4 + pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec4 + ( + .hit (hit[4]), + .addr_out (addr4), + .addr_in (address), + .base_addr (bar4_in), + .mask_addr (am4_in), + .tran_addr (ta4_in), + .at_en (at_en_in[4]) + ) ; +`else + assign hit[4] = 1'b0 ; + assign addr4 = 0 ; +`endif + +`ifdef WB_IMAGE5 + pci_wb_decoder #(`WB_NUM_OF_DEC_ADDR_LINES) dec5 + ( + .hit (hit[5]), + .addr_out (addr5), + .addr_in (address), + .base_addr (bar5_in), + .mask_addr (am5_in), + .tran_addr (ta5_in), + .at_en (at_en_in[5]) + ) ; +`else + assign hit[5] = 1'b0 ; + assign addr5 = 0 ; +`endif + +// address multiplexer +always@ +( + hit or + addr0 or + addr1 or + addr2 or + addr3 or + addr4 or + addr5 +) +begin + case ( {hit[5:2], hit[0]} ) + 5'b0_0_0_0_1: address_out = addr0 ; + 5'b0_0_0_1_0: address_out = addr2 ; + 5'b0_0_1_0_0: address_out = addr3 ; + 5'b0_1_0_0_0: address_out = addr4 ; + 5'b1_0_0_0_0: address_out = addr5 ; + + // default address is address from decoder 1 - it is always implemented - in case of stripped down core to only one image + // this multiplexer can be completely removed during synthesys + default: address_out = addr1 ; + endcase +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v new file mode 100644 index 000000000..3f84a804f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v @@ -0,0 +1,170 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: decoder.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// - Tilen Novak, tilen@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// Tilen Novak, tilen@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_decoder.v,v $ +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.3 2002/02/01 15:25:12 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:28 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_wb_decoder (hit, addr_out, addr_in, base_addr, mask_addr, tran_addr, at_en) ; + +// Decoding address size parameter - for FPGAs 1MegByte is recommended +// MAXIMUM is 20 (4KBytes), length 12 is 1 MByte !!! +parameter decode_len = 12 ; + +//########################################################################################################### +// ALL COMMENTS are written as there were decode_len 20. This number and 12 (32 - 20) are assigning the +// numbers of decoded and compared bits, etc. +//########################################################################################################### + +/*----------------------------------------------------------------------------------------------------------- +DECODER interface decodes input address (ADDR_IN); what means that it validates (HIT), if input address +falls within the defined image space boundaries. Image space boundarie is defined with image base address +register (BASE_ADDR) and address mask register (MASK_ADDR). +Beside that, it also translates (maps) the input address to the output address (ADDR_OUT), regarding the +translation address register (TRAN_ADDR) and the address mask register. +-----------------------------------------------------------------------------------------------------------*/ + +// output control +output hit ; +// output address +output [31:0] addr_out ; +// input address +input [31:0] addr_in ; + +// input registers - 12 LSbits are not valid since the smallest possible size is 4KB ! +input [31:(32-decode_len)] base_addr ; +input [31:(32-decode_len)] mask_addr ; +input [31:(32-decode_len)] tran_addr ; + +// input bit[2] of the Image Control register used to enable the address translation ! +input at_en ; +/*----------------------------------------------------------------------------------------------------------- +Internal signals ! +-----------------------------------------------------------------------------------------------------------*/ + +// bit[31] if address mask register is IMAGE ENABLE bit (img_en) +wire img_en ; + +// addr_in_compare are masked input address bits that are compared with masked base_addr +wire [31:(32-decode_len)] addr_in_compare ; +// base_addr_compare are masked base address bits that are compared with masked addr_in +wire [31:(32-decode_len)] base_addr_compare ; + +/*----------------------------------------------------------------------------------------------------------- +Decoding the input address! +This logic produces the loghest path in this module! + +20 MSbits of input addres are as well as base address (20 bits) masked with corrected address mask. Only +masked bits of each vector are actually logically compared. +Bit[31] of address mask register is used to enable the image space ! +-----------------------------------------------------------------------------------------------------------*/ + +assign addr_in_compare = (addr_in[31:(32-decode_len)] & mask_addr) ; + +assign base_addr_compare = (base_addr & mask_addr) ; + +assign img_en = mask_addr[31] ; + +assign hit = { 1'b1, addr_in_compare } == { img_en, base_addr_compare } ; + +/*----------------------------------------------------------------------------------------------------------- +Translating the input address! + +Translation of input address is not implemented if ADDR_TRAN_IMPL is not defined + +20 MSbits of input address are masked with negated value of the corrected address mask in order to get +address bits of the input address which won't be replaced with translation address bits. +Translation address bits (20 bits) are masked with corrected address mask. Only masked bits of vector are +actually valid, all others are zero. +Boath vectors are bit-wise ORed in order to get the valid translation address with an offset of an input +address. +12 LSbits of an input address are assigned to 12 LSbits of an output addres. +-----------------------------------------------------------------------------------------------------------*/ + +`ifdef ADDR_TRAN_IMPL + // if Address Translation Enable bit is set, then translation address is used othervise input address is used! + // addr_in_combine input address bits are not replaced with translation address! + wire [31:(32-decode_len)] addr_in_combine ; + // tran_addr_combine are masked and combined with addr_in_combine! + reg [31:(32-decode_len)] tran_addr_combine ; + + assign addr_in_combine = (addr_in[31:(32-decode_len)] & ~mask_addr) ; + always@(at_en or tran_addr or mask_addr or addr_in) + begin + if (at_en) + begin + tran_addr_combine <= (tran_addr & mask_addr) ; + end + else + begin + tran_addr_combine <= (addr_in[31:(32-decode_len)] & mask_addr) ; + end + end + + assign addr_out[31:(32-decode_len)] = addr_in_combine | tran_addr_combine ; + assign addr_out[(31-decode_len):0] = addr_in [(31-decode_len):0] ; +`else + assign addr_out = addr_in ; +`endif + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v new file mode 100644 index 000000000..591e2206f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v @@ -0,0 +1,1173 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: wb_master.v //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_master.v,v $ +// Revision 1.6 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.5 2003/10/24 09:35:40 tadejm +// Added missing signals to 2 sensitivity lists. Everything works the same as before. +// +// Revision 1.4 2003/08/21 20:56:40 tadejm +// WB Master is now WISHBONE B3 compatible. +// +// Revision 1.3 2003/03/14 15:31:57 mihad +// Entered the option to disable no response counter in wb master. +// +// Revision 1.2 2003/01/30 22:01:09 mihad +// Updated synchronization in top level fifo modules. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.7 2002/12/05 12:19:23 mihad +// *** empty log message *** +// +// Revision 1.6 2002/10/11 14:15:29 mihad +// Cleaned up non-blocking assignments in combinatinal logic statements +// +// Revision 1.5 2002/03/05 11:53:47 mihad +// Added some testcases, removed un-needed fifo signals +// +// Revision 1.4 2002/02/19 16:32:37 mihad +// Modified testbench and fixed some bugs +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +`define WB_FSM_BITS 3 // number of bits needed for FSM states + + +`include "bus_commands.v" +`include "pci_constants.v" +//synopsys translate_off +`include "timescale.v" +//synopsys translate_on + +module pci_wb_master + ( wb_clock_in, // CLK_I + reset_in, // RST_I + + pci_tar_read_request, + pci_tar_address, + pci_tar_cmd, + pci_tar_be, + pci_tar_burst_ok, + pci_cache_line_size, + cache_lsize_not_zero, + wb_read_done_out, + w_attempt, + + pcir_fifo_wenable_out, + pcir_fifo_data_out, + pcir_fifo_be_out, + pcir_fifo_control_out, + //pcir_fifo_renable_out, for PCI Target !!! + //pcir_fifo_data_in, for PCI Target !!! + //pcir_fifo_be_in, for PCI Target !!! + //pcir_fifo_control_in, for PCI Target !!! + //pcir_fifo_flush_out, for PCI Target !!! + //pcir_fifo_almost_empty_in, for PCI Target !!! + //pcir_fifo_empty_in, NOT used + //pcir_fifo_transaction_ready_in, NOT used + //pciw_fifo_wenable_out, for PCI Target !!! + //pciw_fifo_addr_data_out, for PCI Target !!! + //pciw_fifo_cbe_out, for PCI Target !!! + //pciw_fifo_control_out, for PCI Target !!! + pciw_fifo_renable_out, + pciw_fifo_addr_data_in, + pciw_fifo_cbe_in, + pciw_fifo_control_in, + //pciw_fifo_flush_out, NOT used + //pciw_fifo_almost_full_in, for PCI Target !!! + //pciw_fifo_full_in, for PCI Target !!! + pciw_fifo_almost_empty_in, + pciw_fifo_empty_in, + pciw_fifo_transaction_ready_in, + + pci_error_sig_out, + pci_error_bc, + write_rty_cnt_exp_out, + error_source_out, + read_rty_cnt_exp_out, + + wb_cyc_o, + wb_stb_o, + wb_we_o, + wb_cti_o, + wb_bte_o, + wb_sel_o, + wb_adr_o, + wb_dat_i, + wb_dat_o, + wb_ack_i, + wb_rty_i, + wb_err_i +// CYC_O, +// STB_O, +// WE_O, +// SEL_O, +// ADR_O, +// MDATA_I, +// MDATA_O, +// ACK_I, +// RTY_I, +// ERR_I, + ); + +/*---------------------------------------------------------------------------------------------------------------------- +Various parameters needed for state machine and other stuff +----------------------------------------------------------------------------------------------------------------------*/ +parameter S_IDLE = `WB_FSM_BITS'h0 ; +parameter S_WRITE = `WB_FSM_BITS'h1 ; +parameter S_WRITE_ERR_RTY = `WB_FSM_BITS'h2 ; +parameter S_READ = `WB_FSM_BITS'h3 ; +parameter S_READ_RTY = `WB_FSM_BITS'h4 ; +parameter S_TURN_ARROUND = `WB_FSM_BITS'h5 ; + +/*---------------------------------------------------------------------------------------------------------------------- +System signals inputs +wb_clock_in - WISHBONE bus clock input +reset_in - system reset input controlled by bridge's reset logic +----------------------------------------------------------------------------------------------------------------------*/ +input wb_clock_in ; +input reset_in ; + +/*---------------------------------------------------------------------------------------------------------------------- +Control signals from PCI Target for READS to PCIR_FIFO +---------------------------------------------------------------------------------------------------------------------*/ +input pci_tar_read_request ; // read request from PCI Target +input [31:0] pci_tar_address ; // address for requested read from PCI Target +input [3:0] pci_tar_cmd ; // command for requested read from PCI Target +input [3:0] pci_tar_be ; // byte enables for requested read from PCI Target +input pci_tar_burst_ok ; +input [7:0] pci_cache_line_size ; // CACHE line size register value for burst length +input cache_lsize_not_zero ; +output wb_read_done_out ; // read done and PCIR_FIFO has data ready +output w_attempt ; + +reg wb_read_done_out ; +reg wb_read_done ; + +/*---------------------------------------------------------------------------------------------------------------------- +PCIR_FIFO control signals used for sinking data into PCIR_FIFO and status monitoring +---------------------------------------------------------------------------------------------------------------------*/ +output pcir_fifo_wenable_out ; // PCIR_FIFO write enable output +output [31:0] pcir_fifo_data_out ; // data output to PCIR_FIFO +output [3:0] pcir_fifo_be_out ; // byte enable output to PCIR_FIFO +output [3:0] pcir_fifo_control_out ; // control bus output to PCIR_FIFO + +reg [31:0] pcir_fifo_data_out ; +reg pcir_fifo_wenable_out ; +reg pcir_fifo_wenable ; +reg [3:0] pcir_fifo_control_out ; +reg [3:0] pcir_fifo_control ; + +/*---------------------------------------------------------------------------------------------------------------------- +PCIW_FIFO control signals used for fetching data from PCIW_FIFO and status monitoring +---------------------------------------------------------------------------------------------------------------------*/ +output pciw_fifo_renable_out ; // read enable for PCIW_FIFO output +input [31:0] pciw_fifo_addr_data_in ; // address and data input from PCIW_FIFO +input [3:0] pciw_fifo_cbe_in ; // command and byte_enables from PCIW_FIFO +input [3:0] pciw_fifo_control_in ; // control bus input from PCIW_FIFO +input pciw_fifo_almost_empty_in ; // almost empty status indicator from PCIW_FIFO +input pciw_fifo_empty_in ; // empty status indicator from PCIW_FIFO +input pciw_fifo_transaction_ready_in ; // write transaction is ready in PCIW_FIFO + +reg pciw_fifo_renable_out ; +reg pciw_fifo_renable ; + +/*---------------------------------------------------------------------------------------------------------------------- +Control INPUT / OUTPUT signals for configuration space reporting registers !!! +---------------------------------------------------------------------------------------------------------------------*/ +output pci_error_sig_out ; // When error occures (on WB bus, retry counter, etc.) +output [3:0] pci_error_bc ; // bus command at which error occured ! +output write_rty_cnt_exp_out ; // Signaling that RETRY counter has expired during write transaction! +output read_rty_cnt_exp_out ; // Signaling that RETRY counter has expired during read transaction! + // if error_source is '0' other side didn't respond + // if error_source is '1' other side RETRIED for max retry counter value +output error_source_out ; // Signaling error source - '0' other WB side signaled error OR didn't respond + // if '1' wridge counted max value in retry counter because of RTY responds +reg pci_error_sig_out ; +reg write_rty_cnt_exp_out ; +reg read_rty_cnt_exp_out ; +reg error_source_out ; + +/*---------------------------------------------------------------------------------------------------------------------- +WISHBONE bus interface signals - can be connected directly to WISHBONE bus +---------------------------------------------------------------------------------------------------------------------*/ +output wb_cyc_o; // cycle indicator output +output wb_stb_o; // strobe output - data is valid when strobe and cycle indicator are high +output wb_we_o; // write enable output - 1 - write operation, 0 - read operation +output [2:0] wb_cti_o; // WB B3 - cycle type identifier +output [1:0] wb_bte_o; // WB B3 - burst type +output [3:0] wb_sel_o; // Byte select outputs +output [31:0] wb_adr_o; // WISHBONE address output +input [31:0] wb_dat_i; // WISHBONE interface input data bus +output [31:0] wb_dat_o; // WISHBONE interface output data bus +input wb_ack_i; // Acknowledge input - qualifies valid data on data output bus or received data on data input bus +input wb_rty_i; // retry input - signals from WISHBONE slave that cycle should be terminated and retried later +input wb_err_i; // Signals from WISHBONE slave that access resulted in an error + +reg wb_cyc_o; +reg wb_stb_o; +reg wb_we_o; +reg [2:0] wb_cti_o; +reg [1:0] wb_bte_o; +reg [3:0] wb_sel_o; +reg [31:0] wb_dat_o; + + + +/*########################################################################################################### +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + LOGIC, COUNTERS, STATE MACHINE and some control register bits + ============================================================= +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +###########################################################################################################*/ + +reg last_data_transferred ; // signal is set by STATE MACHINE after each complete transfere ! + +// wire for write attempt - 1 when PCI Target attempt to write and PCIW_FIFO has a write transaction ready +reg w_attempt; +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + w_attempt <= #`FF_DELAY 1'b0; + else + begin + if (pciw_fifo_transaction_ready_in && ~pciw_fifo_empty_in) + w_attempt <= #`FF_DELAY 1'b1; + else + if (last_data_transferred) + w_attempt <= #`FF_DELAY 1'b0; + end +end + +// wire for read attempt - 1 when PCI Target is attempting a read and PCIR_FIFO is not full ! +// because of transaction ordering, PCI Master must not start read untill all writes are done -> at that +// moment PCIW_FIFO is empty !!! (when read is pending PCI Target will block new reads and writes) +wire r_attempt = ( pci_tar_read_request && !w_attempt && pciw_fifo_empty_in ) ; + +// Signal is used for reads on WB, when there is retry! +reg first_wb_data_access ; + +reg last_data_from_pciw_fifo ; // signal tells when there is last data in pciw_fifo +reg last_data_from_pciw_fifo_reg ; +reg last_data_to_pcir_fifo ; // signal tells when there will be last data for pcir_fifo + +// Logic used in State Machine logic implemented out of State Machine because of less delay! +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + last_data_from_pciw_fifo <= #`FF_DELAY 1'b0 ; + else + begin + if ((pciw_fifo_renable_out) && + (pciw_fifo_control_in[`LAST_CTRL_BIT] || pciw_fifo_almost_empty_in)) // if last data is going to be transfered + last_data_from_pciw_fifo <= #`FF_DELAY 1'b1 ; // signal for last data from PCIW_FIFO + else + last_data_from_pciw_fifo <= #`FF_DELAY 1'b0 ; + end +end + + reg read_count_load; + reg read_count_enable; + + reg [(`PCIR_ADDR_LENGTH - 1):0] max_read_count ; + always@(pci_cache_line_size or cache_lsize_not_zero or pci_tar_cmd) + begin + if (cache_lsize_not_zero) + if ( (pci_cache_line_size >= `PCIR_DEPTH) || (~pci_tar_cmd[1] && ~pci_tar_cmd[0]) ) + // If cache line size is larger than FIFO or BC_MEM_READ_MUL command is performed! + max_read_count = `PCIR_DEPTH - 1'b1; + else + max_read_count = pci_cache_line_size ; + else + max_read_count = 1'b1; + end + + reg [(`PCIR_ADDR_LENGTH - 1):0] read_count ; + + // cache line bound indicator - it signals when data for one complete cacheline was read + wire read_bound_comb = ~|( { read_count[(`PCIR_ADDR_LENGTH - 1):2], read_count[0] } ) ; + + reg read_bound ; + always@(posedge wb_clock_in or posedge reset_in) + begin + if ( reset_in ) + read_bound <= #`FF_DELAY 1'b0 ; + else if (read_count_load) + read_bound <= #`FF_DELAY 1'b0 ; + else if ( read_count_enable ) + read_bound <= #`FF_DELAY read_bound_comb ; + end + + // down counter with load + always@(posedge reset_in or posedge wb_clock_in) + begin + if (reset_in) + read_count <= #`FF_DELAY 0 ; + else + if (read_count_load) + read_count <= #`FF_DELAY max_read_count ; + else + if (read_count_enable) + read_count <= #`FF_DELAY read_count - 1'b1 ; + end + +// Logic used in State Machine logic implemented out of State Machine because of less delay! +// definition of signal telling, when there is last data written into FIFO +always@(pci_tar_cmd or pci_tar_burst_ok or read_bound) +begin + // burst is OK for reads when there is ((MEM_READ_LN or MEM_READ_MUL) and AD[1:0]==2'b00) OR + // (MEM_READ and Prefetchable_IMAGE and AD[1:0]==2'b00) -> pci_tar_burst_ok + case ({pci_tar_cmd, pci_tar_burst_ok}) + {`BC_MEM_READ, 1'b1}, + {`BC_MEM_READ_LN, 1'b1} : + begin // when burst cycle + if (read_bound) + last_data_to_pcir_fifo = 1'b1 ; + else + last_data_to_pcir_fifo = 1'b0 ; + end + {`BC_MEM_READ_MUL, 1'b1} : + begin // when burst cycle + if (read_bound) + last_data_to_pcir_fifo = 1'b1 ; + else + last_data_to_pcir_fifo = 1'b0 ; + end + default : + // {`BC_IO_READ, 1'b0}, + // {`BC_IO_READ, 1'b1}, + // {`BC_MEM_READ, 1'b0}, + // {`BC_MEM_READ_LN, 1'b0}, + // {`BC_MEM_READ_MUL, 1'b0}: + begin // when single cycle + last_data_to_pcir_fifo = 1'b1 ; + end + endcase +end + +reg wait_for_wb_response ; + +`ifdef PCI_WBM_NO_RESPONSE_CNT_DISABLE +wire set_retry = 1'b0 ; + +`else +reg [3:0] wb_no_response_cnt ; +reg [3:0] wb_response_value ; +reg set_retry ; // + +// internal WB no response retry generator counter! +always@(posedge reset_in or posedge wb_clock_in) +begin + if (reset_in) + wb_no_response_cnt <= #`FF_DELAY 4'h0 ; + else + wb_no_response_cnt <= #`FF_DELAY wb_response_value ; +end +// internal WB no response retry generator logic +always@(wait_for_wb_response or wb_no_response_cnt) +begin + if (wb_no_response_cnt == 4'h8) // when there isn't response for 8 clocks, set internal retry + begin + wb_response_value = 4'h0 ; + set_retry = 1'b1 ; + end + else + begin + if (wait_for_wb_response) + wb_response_value = wb_no_response_cnt + 1'h1 ; // count clocks when no response + else + wb_response_value = 4'h0 ; + set_retry = 1'b0 ; + end +end +`endif + +wire retry = wb_rty_i || set_retry ; // retry signal - logic OR function between wb_rty_i and internal WB no response retry! +reg [7:0] rty_counter ; // output from retry counter +reg [7:0] rty_counter_in ; // input value - output value + 1 OR output value +reg rty_counter_almost_max_value ; // signal tells when retry counter riches maximum value - 1! +reg reset_rty_cnt ; // signal for asynchronous reset of retry counter after each complete transfere + +// sinchronous signal after each transfere and asynchronous signal 'reset_rty_cnt' after reset +// for reseting the retry counter +always@(posedge reset_in or posedge wb_clock_in) +begin + if (reset_in) + reset_rty_cnt <= #`FF_DELAY 1'b1 ; // asynchronous set when reset signal is active + else + reset_rty_cnt <= #`FF_DELAY wb_ack_i || wb_err_i || last_data_transferred ; // synchronous set after completed transfere +end + +// Retry counter register control +always@(posedge reset_in or posedge wb_clock_in) +begin + if (reset_in) + rty_counter <= #`FF_DELAY 8'h00 ; + else + begin + if (reset_rty_cnt) + rty_counter <= #`FF_DELAY 8'h00 ; + else if (retry) + rty_counter <= #`FF_DELAY rty_counter_in ; + end +end +// Retry counter logic +always@(rty_counter) +begin + if(rty_counter == `WB_RTY_CNT_MAX - 1'b1) // stop counting + begin + rty_counter_in = rty_counter ; + rty_counter_almost_max_value = 1'b1 ; + end + else + begin + rty_counter_in = rty_counter + 1'b1 ; // count up + rty_counter_almost_max_value = 1'b0 ; + end +end + +reg [31:0] addr_cnt_out ; // output value from address counter to WB ADDRESS output +reg [31:0] addr_cnt_in ; // input address value to address counter +reg addr_into_cnt ; // control signal for loading starting address into counter +reg addr_into_cnt_reg ; +reg addr_count ; // control signal for count enable +reg [3:0] bc_register ; // used when error occures during writes! + +// wb address counter register control +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) // reset counter + begin + addr_cnt_out <= #`FF_DELAY 32'h0000_0000 ; + bc_register <= #`FF_DELAY 4'h0 ; + addr_into_cnt_reg <= #`FF_DELAY 1'b0; + end + else + begin + addr_cnt_out <= #`FF_DELAY addr_cnt_in ; // count up or hold value depending on cache line counter logic + addr_into_cnt_reg <= #`FF_DELAY addr_into_cnt; + if (addr_into_cnt) + bc_register <= #`FF_DELAY pciw_fifo_cbe_in ; + end +end + +// when '1', the bus command is IO command - not supported commands are checked in pci_decoder modules +wire io_memory_bus_command = !pci_tar_cmd[3] && !pci_tar_cmd[2] ; + +// wb address counter logic +always@(addr_into_cnt or r_attempt or addr_count or pciw_fifo_addr_data_in or pci_tar_address or addr_cnt_out or + io_memory_bus_command) +begin + if (addr_into_cnt) // load starting address into counter + begin + if (r_attempt) + begin // if read request, then load read addresss from PCI Target + addr_cnt_in = {pci_tar_address[31:2], pci_tar_address[1] && io_memory_bus_command, + pci_tar_address[0] && io_memory_bus_command} ; + end + else + begin // if not read request, then load write address from PCIW_FIFO + addr_cnt_in = pciw_fifo_addr_data_in[31:0] ; + end + end + else + if (addr_count) + begin + addr_cnt_in = addr_cnt_out + 3'h4 ; // count up for 32-bit alligned address + end + else + begin + addr_cnt_in = addr_cnt_out ; + end +end + +reg retried ; // Signal is output value from FF and is set for one clock period after retried_d is set +reg retried_d ; // Signal is set whenever cycle is retried and is input to FF for delaying -> used in S_IDLE state +reg retried_write; +reg rty_i_delayed; // Dignal used for determinig the source of retry! + +reg first_data_is_burst ; // Signal is set in S_WRITE or S_READ states, when data transfere is burst! +reg first_data_is_burst_reg ; +wire burst_transfer ; // This signal is set when data transfere is burst and is reset with RESET or last data transfered +reg burst_chopped; // This signal is set when WB_SEL_O is changed during burst write transaction +reg burst_chopped_delayed; + +// FFs output signals tell, when there is first data out from FIFO (for BURST checking) +// and for delaying retried signal +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) // reset signals + begin + retried <= #`FF_DELAY 1'b0 ; + retried_write <= #`FF_DELAY 1'b0 ; + rty_i_delayed <= #`FF_DELAY 1'B0 ; + end + else + begin + retried <= #`FF_DELAY retried_d ; // delaying retried signal + retried_write <= #`FF_DELAY retried ; + rty_i_delayed <= #`FF_DELAY wb_rty_i ; + end +end + +// Determinig if first data is a part of BURST or just a single transfere! +always@(addr_into_cnt or r_attempt or pci_tar_burst_ok or max_read_count or + pciw_fifo_control_in or pciw_fifo_empty_in) +begin + if (addr_into_cnt) + begin + if (r_attempt) + begin + // burst is OK for reads when there is ((MEM_READ_LN or MEM_READ_MUL) and AD[1:0]==2'b00) OR + // (MEM_READ and Prefetchable_IMAGE and AD[1:0]==2'b00) -> pci_tar_burst_ok + if (pci_tar_burst_ok && (max_read_count != 8'h1)) + first_data_is_burst = 1'b1 ; + else + first_data_is_burst = 1'b0 ; + end + else + begin + first_data_is_burst = 1'b0 ; + end + end + else + first_data_is_burst = pciw_fifo_control_in[`BURST_BIT] && ~pciw_fifo_empty_in && + ~pciw_fifo_control_in[`LAST_CTRL_BIT] /*&& ~pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT]*/; +end + +// FF for seting and reseting burst_transfer signal +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + begin + burst_chopped <= #`FF_DELAY 1'b0; + burst_chopped_delayed <= #`FF_DELAY 1'b0; + first_data_is_burst_reg <= #`FF_DELAY 1'b0 ; + end + else + begin + if (pciw_fifo_transaction_ready_in) + begin + if (pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT]) + burst_chopped <= #`FF_DELAY 1'b1; + else if (wb_ack_i || wb_err_i || wb_rty_i) + burst_chopped <= #`FF_DELAY 1'b0; + end + else + burst_chopped <= #`FF_DELAY 1'b0; + burst_chopped_delayed <= #`FF_DELAY burst_chopped; + if (last_data_transferred || first_data_is_burst) + first_data_is_burst_reg <= #`FF_DELAY ~last_data_transferred ; + end +end +assign burst_transfer = first_data_is_burst || first_data_is_burst_reg ; + +reg [(`WB_FSM_BITS - 1):0] c_state ; //current state register +reg [(`WB_FSM_BITS - 1):0] n_state ; //next state input to current state register + +//################################## +// WISHBONE B3 master state machine +//################################## + +// state machine register control and registered outputs (without wb_adr_o counter) +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) // reset state machine to S_IDLE state + begin + c_state <= #`FF_DELAY S_IDLE; + wb_cyc_o <= #`FF_DELAY 1'b0; + wb_stb_o <= #`FF_DELAY 1'b0; + wb_we_o <= #`FF_DELAY 1'b0; + wb_cti_o <= #`FF_DELAY 3'h2; + wb_bte_o <= #`FF_DELAY 2'h0; + wb_sel_o <= #`FF_DELAY 4'h0; + wb_dat_o <= #`FF_DELAY 32'h0; + pcir_fifo_data_out <= #`FF_DELAY 32'h0; + pcir_fifo_control_out <= #`FF_DELAY 4'h0; + pcir_fifo_wenable_out <= #`FF_DELAY 1'b0; + end + else + begin + c_state <= #`FF_DELAY n_state; + wb_bte_o <= #`FF_DELAY 2'h0; + case (n_state) // synthesis parallel_case full_case + S_WRITE: + begin + wb_cyc_o <= #`FF_DELAY ~addr_into_cnt; + wb_stb_o <= #`FF_DELAY ~addr_into_cnt; + wb_we_o <= #`FF_DELAY ~addr_into_cnt; + // if '1' then next burst BE is not equat to current one => burst is chopped into singles + // OR if last data is going to be transfered + if ((wb_stb_o && wb_ack_i) || addr_into_cnt_reg || (~wb_cyc_o && (retried || burst_chopped_delayed))) + begin + if (burst_transfer && ~pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT] && + ~(pciw_fifo_renable_out && (pciw_fifo_control_in[`LAST_CTRL_BIT] || pciw_fifo_almost_empty_in))) + wb_cti_o <= #`FF_DELAY 3'h2; + else + wb_cti_o <= #`FF_DELAY 3'h7; + end + if ((pciw_fifo_renable_out && ~addr_into_cnt) || addr_into_cnt_reg) + begin + wb_sel_o <= #`FF_DELAY ~pciw_fifo_cbe_in; + wb_dat_o <= #`FF_DELAY pciw_fifo_addr_data_in; + end + end + S_WRITE_ERR_RTY: + begin + wb_cyc_o <= #`FF_DELAY 1'b0; + wb_stb_o <= #`FF_DELAY 1'b0; + wb_we_o <= #`FF_DELAY 1'b0; + wb_cti_o <= #`FF_DELAY 3'h2; + // stay the same as previous + //wb_sel_o <= #`FF_DELAY 4'h0; + //wb_dat_o <= #`FF_DELAY 32'h0; + end + S_READ: + begin + wb_cyc_o <= #`FF_DELAY ~addr_into_cnt; + wb_stb_o <= #`FF_DELAY ~addr_into_cnt; + wb_we_o <= #`FF_DELAY 1'b0; + if ((wb_stb_o && wb_ack_i) || addr_into_cnt_reg || (~wb_cyc_o && retried)) + begin + if (burst_transfer && ~read_bound_comb) + wb_cti_o <= #`FF_DELAY 3'h2; + else + wb_cti_o <= #`FF_DELAY 3'h7; + end + if (burst_transfer) + wb_sel_o <= #`FF_DELAY 4'hF; + else + wb_sel_o <= #`FF_DELAY ~pci_tar_be; + // no need to change att all + //wb_dat_o <= #`FF_DELAY 32'h0; + end + S_READ_RTY: + begin + wb_cyc_o <= #`FF_DELAY 1'b0; + wb_stb_o <= #`FF_DELAY 1'b0; + wb_we_o <= #`FF_DELAY 1'b0; + wb_cti_o <= #`FF_DELAY 3'h2; + // no need to change att all + //wb_sel_o <= #`FF_DELAY 4'h0; + //wb_dat_o <= #`FF_DELAY 32'h0; + end + S_TURN_ARROUND: + begin + wb_cyc_o <= #`FF_DELAY 1'b0; + wb_stb_o <= #`FF_DELAY 1'b0; + wb_we_o <= #`FF_DELAY 1'b0; + wb_cti_o <= #`FF_DELAY 3'h2; + // no need to change att all + //wb_sel_o <= #`FF_DELAY 4'h0; + //wb_dat_o <= #`FF_DELAY 32'h0; + end + default: // S_IDLE: + begin + wb_cyc_o <= #`FF_DELAY 1'b0; + wb_stb_o <= #`FF_DELAY 1'b0; + wb_we_o <= #`FF_DELAY 1'b0; + wb_cti_o <= #`FF_DELAY 3'h2; + // no need to change att all + //wb_sel_o <= #`FF_DELAY 4'h0; + //wb_dat_o <= #`FF_DELAY 32'h0; + end + endcase + pcir_fifo_data_out <= #`FF_DELAY wb_dat_i; + pcir_fifo_control_out <= #`FF_DELAY pcir_fifo_control ; + pcir_fifo_wenable_out <= #`FF_DELAY pcir_fifo_wenable ; + end +end + +assign wb_adr_o = addr_cnt_out ; + +// state machine logic +always@(c_state or + wb_ack_i or + wb_rty_i or + wb_err_i or + w_attempt or + r_attempt or + retried or + burst_chopped or + burst_chopped_delayed or + rty_i_delayed or + pci_tar_read_request or + rty_counter_almost_max_value or + set_retry or + last_data_to_pcir_fifo or + first_wb_data_access or + pciw_fifo_control_in or + pciw_fifo_empty_in or + burst_transfer or + last_data_from_pciw_fifo_reg + ) +begin + case (c_state) + S_IDLE: + begin + // Default values for signals not used in this state + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_count = 1'b0 ; + read_count_enable = 1'b0 ; + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + retried_d = 1'b0 ; + last_data_transferred = 1'b0 ; + wb_read_done = 1'b0 ; + wait_for_wb_response = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; + pci_error_sig_out = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + case ({w_attempt, r_attempt, retried}) + 3'b101 : // Write request for PCIW_FIFO to WB bus transaction + begin // If there was retry, the same transaction must be initiated + pciw_fifo_renable = 1'b0 ; // the same data + addr_into_cnt = 1'b0 ; // the same address + read_count_load = 1'b0 ; // no need for cache line when there is write + n_state = S_WRITE ; + end + 3'b100 : // Write request for PCIW_FIFO to WB bus transaction + begin // If there is new transaction + if (burst_chopped_delayed) + begin + addr_into_cnt = 1'b0 ; // address must not be latched into address counter + pciw_fifo_renable = 1'b1 ; // first location is address (in FIFO), next will be data + end + else + begin + if (pciw_fifo_control_in[`ADDR_CTRL_BIT]) + addr_into_cnt = 1'b1 ; // address must be latched into address counter + else + addr_into_cnt = 1'b0 ; + pciw_fifo_renable = 1'b1 ; // first location is address (in FIFO), next will be data + end + read_count_load = 1'b0 ; // no need for cache line when there is write + n_state = S_WRITE ; + end + 3'b011 : // Read request from PCI Target for WB bus to PCIR_FIFO transaction + begin // If there was retry, the same transaction must be initiated + addr_into_cnt = 1'b0 ; // the same address + read_count_load = 1'b0 ; // cache line counter must not be changed for retried read + pciw_fifo_renable = 1'b0 ; // don't read from FIFO, when read transaction from WB to FIFO + n_state = S_READ ; + end + 3'b010 : // Read request from PCI Target for WB bus to PCIR_FIFO transaction + begin // If there is new transaction + addr_into_cnt = 1'b1 ; // address must be latched into counter from separate request bus + read_count_load = 1'b1 ; // cache line size must be latched into its counter + pciw_fifo_renable = 1'b0 ; // don't read from FIFO, when read transaction from WB to FIFO + n_state = S_READ ; + end + default : // stay in IDLE state + begin + pciw_fifo_renable = 1'b0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + n_state = S_IDLE ; + end + endcase + end + S_WRITE: // WRITE from PCIW_FIFO to WB bus + begin + // Default values for signals not used in this state + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + read_count_enable = 1'b0 ; + wb_read_done = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + case ({wb_ack_i, wb_err_i, wb_rty_i}) + 3'b100 : // If writting of one data is acknowledged + begin + addr_count = 1'b1 ; // prepare next address if there will be burst + retried_d = 1'b0 ; // there was no retry + pci_error_sig_out = 1'b0 ; // there was no error + error_source_out = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; // there was no retry + wait_for_wb_response = 1'b0 ; + // if last data was transfered ! + if (last_data_from_pciw_fifo_reg) + begin + n_state = S_TURN_ARROUND; + if (~pciw_fifo_empty_in) + pciw_fifo_renable = 1'b0 ; // prepare next value (address when new trans., data when burst tran.) + else + pciw_fifo_renable = 1'b0 ; + last_data_transferred = 1'b1 ; // signal for last data transfered + end + // next burst data has different byte enables ! + else if (burst_transfer && burst_chopped) + begin + n_state = S_IDLE ; + pciw_fifo_renable = 1'b0 ; // next value (address when new trans., data when burst tran.) + last_data_transferred = 1'b0 ; + end + else + begin + n_state = S_WRITE ; + pciw_fifo_renable = 1'b1 ; // prepare next value (address when new trans., data when burst tran.) + last_data_transferred = 1'b0 ; + end + end + 3'b010 : // If writting of one data is terminated with ERROR + begin + if (~pciw_fifo_empty_in) + pciw_fifo_renable = 1'b1 ; // prepare next value (address when new trans., data when cleaning FIFO) + else + pciw_fifo_renable = 1'b0 ; + addr_count = 1'b0 ; // no need for new address + retried_d = 1'b0 ; // there was no retry + last_data_transferred = 1'b1 ; // signal for last data transfered + pci_error_sig_out = 1'b1 ; // segnal for error reporting + error_source_out = 1'b0 ; // error source from other side of WB bus + write_rty_cnt_exp_out = 1'b0 ; // there was no retry + wait_for_wb_response = 1'b0 ; + if (last_data_from_pciw_fifo_reg) // if last data was transfered + n_state = S_TURN_ARROUND ; // go to S_TURN_ARROUND for new transfere + else // if there wasn't last data of transfere + n_state = S_WRITE_ERR_RTY ; // go here to clean this write transaction from PCIW_FIFO + end + 3'b001 : // If writting of one data is retried + begin + addr_count = 1'b0 ; + last_data_transferred = 1'b0 ; + retried_d = 1'b1 ; // there was a retry + wait_for_wb_response = 1'b0 ; + if(rty_counter_almost_max_value) // If retry counter reached maximum allowed value + begin + if (last_data_from_pciw_fifo_reg) // if last data was transfered + pciw_fifo_renable = 1'b0 ; + else // if there wasn't last data of transfere + pciw_fifo_renable = 1'b1 ; + n_state = S_WRITE_ERR_RTY ; // go here to clean this write transaction from PCIW_FIFO + write_rty_cnt_exp_out = 1'b1 ; // signal for reporting write counter expired + pci_error_sig_out = 1'b1 ; + error_source_out = 1'b1 ; // error ocuerd because of retry counter + end + else + begin + pciw_fifo_renable = 1'b0 ; + n_state = S_IDLE ; // go to S_IDLE state for retrying the transaction + write_rty_cnt_exp_out = 1'b0 ; // retry counter hasn't expired yet + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + end + end + default : + begin + addr_count = 1'b0 ; + last_data_transferred = 1'b0 ; + wait_for_wb_response = 1'b1 ; // wait for WB device to response (after 8 clocks RTY CNT is incremented) + error_source_out = 1'b0 ; // if error ocures, error source is from other WB bus side + if((rty_counter_almost_max_value)&&(set_retry)) // when no WB response and RTY CNT reached maximum allowed value + begin + retried_d = 1'b1 ; + if (last_data_from_pciw_fifo_reg) // if last data was transfered + pciw_fifo_renable = 1'b0 ; + else // if there wasn't last data of transfere + pciw_fifo_renable = 1'b1 ; + n_state = S_WRITE_ERR_RTY ; // go here to clean this write transaction from PCIW_FIFO + write_rty_cnt_exp_out = 1'b1 ; // signal for reporting write counter expired + pci_error_sig_out = 1'b1 ; // signal for error reporting + end + else + begin + pciw_fifo_renable = 1'b0 ; + retried_d = 1'b0 ; + n_state = S_WRITE ; // stay in S_WRITE state to wait WB to response + write_rty_cnt_exp_out = 1'b0 ; // retry counter hasn't expired yet + pci_error_sig_out = 1'b0 ; + end + end + endcase + end + S_WRITE_ERR_RTY: // Clean current write transaction from PCIW_FIFO if ERROR or Retry counter expired occures + begin + pciw_fifo_renable = !last_data_from_pciw_fifo_reg ; // put out next data (untill last data or FIFO empty) + last_data_transferred = 1'b1 ; // after exiting this state, negedge of this signal is used + // Default values for signals not used in this state + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + read_count_enable = 1'b0 ; + addr_count = 1'b0 ; + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + retried_d = 1'b0 ; + wb_read_done = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + wait_for_wb_response = 1'b0 ; + // If last data is cleaned out from PCIW_FIFO + if (last_data_from_pciw_fifo_reg) + n_state = S_IDLE ; + else + n_state = S_WRITE_ERR_RTY ; // Clean until last data is cleaned out from FIFO + end + S_READ: // READ from WB bus to PCIR_FIFO + begin + // Default values for signals not used in this state + pciw_fifo_renable = 1'b0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; + case ({wb_ack_i, wb_err_i, wb_rty_i}) + 3'b100 : // If reading of one data is acknowledged + begin + pcir_fifo_wenable = 1'b1 ; // enable writting data into PCIR_FIFO + addr_count = 1'b1 ; // prepare next address if there will be burst + read_count_enable = 1'b1 ; // decrease counter value for cache line size + retried_d = 1'b0 ; // there was no retry + read_rty_cnt_exp_out = 1'b0 ; // there was no retry + wait_for_wb_response = 1'b0 ; + // if last data was transfered + if (last_data_to_pcir_fifo) + begin + pcir_fifo_control[`LAST_CTRL_BIT] = 1'b1 ; // FIFO must indicate LAST data transfered + pcir_fifo_control[`DATA_ERROR_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`UNUSED_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`ADDR_CTRL_BIT] = 1'b0 ; + last_data_transferred = 1'b1 ; // signal for last data transfered + wb_read_done = 1'b1 ; // signal last data of read transaction for PCI Target + n_state = S_TURN_ARROUND ; + end + else // if not last data transfered + begin + pcir_fifo_control = 4'h0 ; // ZERO for control code + last_data_transferred = 1'b0 ; // not last data transfered + wb_read_done = 1'b0 ; // read is not done yet + n_state = S_READ ; + end + end + 3'b010 : // If reading of one data is terminated with ERROR + begin + pcir_fifo_wenable = 1'b1 ; // enable for writting to FIFO data with ERROR + addr_count = 1'b0 ; // no need for new address + pcir_fifo_control[`LAST_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`DATA_ERROR_CTRL_BIT] = 1'b1 ; // FIFO must indicate the DATA with ERROR + pcir_fifo_control[`UNUSED_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`ADDR_CTRL_BIT] = 1'b0 ; + last_data_transferred = 1'b1 ; // signal for last data transfered + wb_read_done = 1'b1 ; // signal last data of read transaction for PCI Target + read_count_enable = 1'b0 ; // no need for cache line, when error occures + n_state = S_TURN_ARROUND ; + retried_d = 1'b0 ; // there was no retry + wait_for_wb_response = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; // there was no retry + end + 3'b001 : // If reading of one data is retried + begin + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_count = 1'b0 ; + read_count_enable = 1'b0 ; + wait_for_wb_response = 1'b0 ; + case ({first_wb_data_access, rty_counter_almost_max_value}) + 2'b10 : + begin // if first data of the cycle (CYC_O) is retried - after each retry CYC_O goes inactive + n_state = S_IDLE ; // go to S_IDLE state for retrying the transaction + read_rty_cnt_exp_out = 1'b0 ; // retry counter hasn't expired yet + last_data_transferred = 1'b0 ; + wb_read_done = 1'b0 ; + retried_d = 1'b1 ; // there was a retry + end + 2'b11 : + begin // if retry counter reached maximum value + n_state = S_READ_RTY ; // go here to wait for PCI Target to remove read request + read_rty_cnt_exp_out = 1'b1 ; // signal for reporting read counter expired + last_data_transferred = 1'b0 ; + wb_read_done = 1'b0 ; + retried_d = 1'b1 ; // there was a retry + end + default : // if retry occures after at least 1 data was transferred without breaking cycle (CYC_O inactive) + begin // then PCI device will retry access! + n_state = S_TURN_ARROUND ; // go to S_TURN_ARROUND state + read_rty_cnt_exp_out = 1'b0 ; // retry counter hasn't expired + last_data_transferred = 1'b1 ; + wb_read_done = 1'b1 ; + retried_d = 1'b0 ; // retry must not be retried, since there is not a first data + end + endcase + end + default : + begin + addr_count = 1'b0 ; + read_count_enable = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + wait_for_wb_response = 1'b1 ; // wait for WB device to response (after 8 clocks RTY CNT is incremented) + if((rty_counter_almost_max_value)&&(set_retry)) // when no WB response and RTY CNT reached maximum allowed value + begin + retried_d = 1'b1 ; + n_state = S_TURN_ARROUND ; // go here to stop read request + pcir_fifo_wenable = 1'b1 ; + pcir_fifo_control[`LAST_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`DATA_ERROR_CTRL_BIT] = 1'b1 ; // FIFO must indicate the DATA with ERROR + pcir_fifo_control[`UNUSED_CTRL_BIT] = 1'b0 ; + pcir_fifo_control[`ADDR_CTRL_BIT] = 1'b0 ; + last_data_transferred = 1'b1 ; + wb_read_done = 1'b1 ; + end + else + begin + retried_d = 1'b0 ; + n_state = S_READ ; // stay in S_READ state to wait WB to response + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + last_data_transferred = 1'b0 ; + wb_read_done = 1'b0 ; + end + end + endcase + end + S_READ_RTY: // Wait for PCI Target to remove read request, when retry counter reaches maximum value! + begin + // Default values for signals not used in this state + pciw_fifo_renable = 1'b0 ; + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + read_count_enable = 1'b0 ; + addr_count = 1'b0 ; + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + retried_d = 1'b0 ; + wb_read_done = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + wait_for_wb_response = 1'b0 ; + // wait for PCI Target to remove read request + if (pci_tar_read_request) + begin + n_state = S_READ_RTY ; // stay in this state until read request is removed + last_data_transferred = 1'b0 ; + end + else // when read request is removed + begin + n_state = S_IDLE ; + last_data_transferred = 1'b1 ; // when read request is removed, there is "last" data + end + end + // Turn arround cycle after writting to PCIR_FIFO (for correct data when reading from PCIW_FIFO) + default: // S_TURN_ARROUND: + begin + // Default values for signals not used in this state + pciw_fifo_renable = 1'b0 ; + pcir_fifo_wenable = 1'b0 ; + pcir_fifo_control = 4'h0 ; + addr_into_cnt = 1'b0 ; + read_count_load = 1'b0 ; + read_count_enable = 1'b0 ; + addr_count = 1'b0 ; + pci_error_sig_out = 1'b0 ; + error_source_out = 1'b0 ; + retried_d = 1'b0 ; + last_data_transferred = 1'b1 ; + wb_read_done = 1'b0 ; + write_rty_cnt_exp_out = 1'b0 ; + read_rty_cnt_exp_out = 1'b0 ; + wait_for_wb_response = 1'b0 ; + n_state = S_IDLE ; + end + endcase +end + +// Signal for retry monitor in state machine when there is read and first (or single) data access +wire ack_rty_response = wb_ack_i || wb_rty_i ; + +// Signal first_wb_data_access is set when no WB cycle present till end of first data access of WB cycle on WB bus +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + first_wb_data_access = 1'b1 ; + else + begin + if (~wb_cyc_o) + first_wb_data_access = 1'b1 ; + else if (ack_rty_response) + first_wb_data_access = 1'b0 ; + end +end + +// Signals to FIFO +assign pcir_fifo_be_out = 4'hf ; // pci_tar_be ; + +// Signals to Conf. space +assign pci_error_bc = bc_register ; + + +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + wb_read_done_out <= #`FF_DELAY 1'b0 ; + else + wb_read_done_out <= #`FF_DELAY wb_read_done ; +end + +always@(pciw_fifo_renable or addr_into_cnt_reg or pciw_fifo_control_in or pciw_fifo_empty_in) +begin + pciw_fifo_renable_out = pciw_fifo_renable || addr_into_cnt_reg ; + last_data_from_pciw_fifo_reg = pciw_fifo_control_in[`ADDR_CTRL_BIT] || pciw_fifo_empty_in ; +end + + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v new file mode 100644 index 000000000..4e389705d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v @@ -0,0 +1,1147 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "wb_slave.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_slave.v,v $ +// Revision 1.5 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.4 2003/12/19 11:11:30 mihad +// Compact PCI Hot Swap support added. +// New testcases added. +// Specification updated. +// Test application changed to support WB B3 cycles. +// +// Revision 1.3 2003/08/14 18:01:53 simons +// ifdefs moved to thier own lines, this confuses some of the tools. +// +// Revision 1.2 2003/08/03 18:05:06 mihad +// Added limited WISHBONE B3 support for WISHBONE Slave Unit. +// Doesn't support full speed bursts yet. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.4 2002/08/19 16:54:25 mihad +// Got rid of undef directives +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:47 mihad +// New project directory structure +// +// + +`include "bus_commands.v" +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_wb_slave + ( wb_clock_in, + reset_in, + wb_hit_in, + wb_conf_hit_in, + wb_map_in, + wb_pref_en_in, + wb_mrl_en_in, + wb_addr_in, + del_bc_in, + wb_del_req_pending_in, + wb_del_comp_pending_in, + pci_drcomp_pending_in, + del_bc_out, + del_req_out, + del_done_out, + del_burst_out, + del_write_out, + del_write_in, + del_error_in, + del_in_progress_out, + ccyc_addr_in, + wb_del_addr_in, + wb_del_be_in, + wb_conf_offset_out, + wb_conf_renable_out, + wb_conf_wenable_out, + wb_conf_be_out, + wb_conf_data_in, + wb_conf_data_out, + wb_data_out, + wb_cbe_out, + wbw_fifo_wenable_out, + wbw_fifo_control_out, + wbw_fifo_almost_full_in, + wbw_fifo_full_in, + wbr_fifo_renable_out, + wbr_fifo_be_in, + wbr_fifo_data_in, + wbr_fifo_control_in, + wbr_fifo_flush_out, + wbr_fifo_empty_in, + pciw_fifo_empty_in, + wbs_lock_in, + init_complete_in, + cache_line_size_not_zero, + sample_address_out, + CYC_I, + STB_I, + WE_I, + SEL_I, + SDATA_I, + SDATA_O, + ACK_O, + RTY_O, + ERR_O, + CAB_I + ); + +/*---------------------------------------------------------------------------------------------------------------------- +Various parameters needed for state machine and other stuff +----------------------------------------------------------------------------------------------------------------------*/ +parameter WBR_SEL = 1'b0 ; +parameter CONF_SEL = 1'b1 ; + +`define FSM_BITS 3 +parameter S_IDLE = `FSM_BITS'h0 ; +parameter S_DEC1 = `FSM_BITS'h1 ; +parameter S_DEC2 = `FSM_BITS'h2 ; +parameter S_START = `FSM_BITS'h3 ; +parameter S_W_ADDR_DATA = `FSM_BITS'h4 ; +parameter S_READ = `FSM_BITS'h5 ; +parameter S_CONF_WRITE = `FSM_BITS'h6 ; +parameter S_CONF_READ = `FSM_BITS'h7 ; + +/*---------------------------------------------------------------------------------------------------------------------- +System signals inputs +wb_clock_in - WISHBONE bus clock input +reset_in - system reset input controlled by bridge's reset logic +----------------------------------------------------------------------------------------------------------------------*/ +input wb_clock_in, reset_in ; + +/*---------------------------------------------------------------------------------------------------------------------- +Inputs from address decoding logic +wb_hit_in - Decoder logic indicates if address is in a range of one of images +wb_conf_hit_in - Decoder logic indicates that address is in configuration space range +wb_map_in - Decoder logic provides information about image mapping - memory mapped image - wb_map_in = 0 + IO space mapped image - wb_map_in = 1 +wb_pref_en_in - Prefetch enable signal from currently selected image - used for PCI bus command usage +wb_addr_in - Address already transalted from WB bus to PCI bus input +wb_mrl_en_in - Memory read line enable input for each image +----------------------------------------------------------------------------------------------------------------------*/ +input [4:0] wb_hit_in ; // hit indicators +input wb_conf_hit_in ; // configuration hit indicator +input [4:0] wb_pref_en_in ; // prefetch enable from all images +input [4:0] wb_mrl_en_in ; // Memory Read line command enable from images +input [4:0] wb_map_in ; // address space mapping indicators - 1 memory space mapping, 0-IO space mapping +input [31:0] wb_addr_in ; // Translated address input + +/*---------------------------------------------------------------------------------------------------------------------- +Delayed transaction control inputs and outputs: +Used for locking particular accesses when delayed transactions are in progress: +wb_del_addr_in - delayed transaction address input - when completion is ready it's used for transaction decoding +wb_del_be_in - delayed transaction byte enable input - when completion is ready it's used for transaction decoding +----------------------------------------------------------------------------------------------------------------------*/ +input [31:0] wb_del_addr_in ; +input [3:0] wb_del_be_in ; + +input [3:0] del_bc_in ; // delayed request bus command used +input wb_del_req_pending_in ; // delayed request pending indicator +input wb_del_comp_pending_in ; // delayed completion pending indicator +input pci_drcomp_pending_in ; // PCI initiated delayed read completion pending + +output [3:0] del_bc_out ; // delayed transaction bus command output + +output del_req_out ; // output for issuing delayed transaction requests + +output del_done_out ; // output indicating current delayed completion finished on WISHBONE bus + +output del_burst_out ; // delayed burst transaction indicator + +output del_in_progress_out ; // delayed in progress indicator - since delayed transaction can be a burst transaction, progress indicator must be used for proper operation + +output del_write_out ; // write enable for delayed transaction - used for indicating that transaction is a write + +input del_write_in ; // indicates that current delayed completion is from a write request +input del_error_in ; // indicate that delayed request terminated with an error - used for write requests + +input [31:0] ccyc_addr_in ; // configuration cycle address input - it's separate from other addresses, since it is stored separately and decoded for type 0 configuration access + +/*---------------------------------------------------------------------------------------------------------------------- +Configuration space access control and data signals +wb_conf_offset_out - lower 12 bits of address input provided for register offset +wb_conf_renable - read enable signal for configuration space accesses +wb_conf_wenable - write enable signal for configuration space accesses +wb_conf_be_out - byte enable signals for configuration space accesses +wb_conf_data_in - data from configuration space +wb_conf_data_in - data provided for configuration space +----------------------------------------------------------------------------------------------------------------------*/ +output [11:0] wb_conf_offset_out ; // register offset output +output wb_conf_renable_out, // configuration read and write enable outputs + wb_conf_wenable_out ; +output [3:0] wb_conf_be_out ; // byte enable outputs for configuration space +input [31:0] wb_conf_data_in ; // configuration data input from configuration space +output [31:0] wb_conf_data_out ; // configuration data output for configuration space + +/*---------------------------------------------------------------------------------------------------------------------- +Data from WISHBONE bus output to interiror of the core: +Data output is used for normal and configuration accesses. +---------------------------------------------------------------------------------------------------------------------*/ +output [31:0] wb_data_out ; + +/*---------------------------------------------------------------------------------------------------------------------- +Bus command - byte enable output - during address phase of image access this bus holds information about PCI +bus command that should be used, during dataphases ( configuration or image access ) this bus contains inverted +SEL_I signals +---------------------------------------------------------------------------------------------------------------------*/ +output [3:0] wb_cbe_out ; + +/*---------------------------------------------------------------------------------------------------------------------- +WBW_FIFO control signals used for sinking data into WBW_FIFO and status monitoring +---------------------------------------------------------------------------------------------------------------------*/ +output wbw_fifo_wenable_out ; // write enable for WBW_FIFO output +output [3:0] wbw_fifo_control_out ; // control bus output for WBW_FIFO +input wbw_fifo_almost_full_in ; // almost full status indicator from WBW_FIFO +input wbw_fifo_full_in ; // full status indicator from WBW_FIFO + +/*---------------------------------------------------------------------------------------------------------------------- +WBR_FIFO control signals used for fetching data from WBR_FIFO and status monitoring +---------------------------------------------------------------------------------------------------------------------*/ +output wbr_fifo_renable_out ; // WBR_FIFO read enable output +input [3:0] wbr_fifo_be_in ; // byte enable input from WBR_FIFO +input [31:0] wbr_fifo_data_in ; // data input from WBR_FIFO +input [3:0] wbr_fifo_control_in ; // control bus input from WBR_FIFO +output wbr_fifo_flush_out ; // flush signal for WBR_FIFO +input wbr_fifo_empty_in ; // empty status indicator from WBR_FIFO + +// used for transaction ordering requirements - WISHBONE read cannot complete until writes from PCI are completed +input pciw_fifo_empty_in ; // empty status indicator from PCIW_FIFO + +/*---------------------------------------------------------------------------------------------------------------------- +wbs_lock_in: internal signal that locks out all accesses, except delayed completions or configuration accesses. +( when master operation is disabled via master enable bit in configuration spacei ) +init_complete_in: while initialization sequence is in progress, the state machine +remains in the idle state - it does not respond to accesses. +---------------------------------------------------------------------------------------------------------------------*/ +input wbs_lock_in ; +input init_complete_in ; + +// cache line size register must hold appropriate value to enable read bursts and special commands on PCI bus! +input cache_line_size_not_zero ; + +// state machine signals to wb_addr_mux when to sample wb address input +output sample_address_out ; +reg sample_address_out ; + +/*---------------------------------------------------------------------------------------------------------------------- +WISHBONE bus interface signals - can be connected directly to WISHBONE bus +---------------------------------------------------------------------------------------------------------------------*/ +input CYC_I ; // cycle indicator +input STB_I ; // strobe input - input data is valid when strobe and cycle indicator are high +input WE_I ; // write enable input - 1 - write operation, 0 - read operation +input [3:0] SEL_I ; // Byte select inputs +input [31:0] SDATA_I ; // WISHBONE slave interface input data bus +output [31:0] SDATA_O ; // WISHBONE slave interface output data bus +output ACK_O ; // Acknowledge output - qualifies valid data on data output bus or received data on data input bus +output RTY_O ; // retry output - signals to WISHBONE master that cycle should be terminated and retried later +output ERR_O ; // Signals to WISHBONE master that access resulted in an error +input CAB_I ; // consecutive address burst input - indicates that master will do a serial address transfer in current cycle + +`ifdef REGISTER_WBS_OUTPUTS +reg [31:0] SDATA_O ; +reg ACK_O ; +reg RTY_O ; +reg ERR_O ; + +reg [3:0] del_bc_out ; // delayed transaction bus command output +reg del_req_out ; // output for issuing delayed transaction requests +reg del_done_out ; // output indicating current delayed completion finished on WISHBONE bus +reg del_burst_out ; // delayed burst transaction indicator +reg del_in_progress_out ; // delayed in progress indicator - since delayed transaction can be a burst transaction, progress indicator must be used for proper operation +reg del_write_out ; // write enable for delayed transaction - used for indicating that transaction is a write + +`ifdef HOST +reg wb_conf_wenable_out ; +reg [31:0] wb_conf_data_out ; // configuration data output for configuration space +`endif + +reg [3:0] wb_conf_be_out ; // byte enable outputs for configuration space +reg [31:0] wb_data_out ; + +reg [3:0] wb_cbe_out ; + +reg wbw_fifo_wenable_out ; // write enable for WBW_FIFO output +reg [3:0] wbw_fifo_control_out ; // control bus output for WBW_FIFO + +reg wbr_fifo_renable_out ; // WBR_FIFO read enable output +`endif + +reg [(`FSM_BITS - 1):0] c_state ; //current state register + +reg [(`FSM_BITS - 1):0] n_state ; //next state input to current state register + +// state machine register control +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + c_state <= #`FF_DELAY S_IDLE ; + else + c_state <= #`FF_DELAY n_state ; +end + + +// variable for bus command multiplexer logic output for delayed requests +reg [3:0] del_bc ; + +//register for intermediate data and select storage +reg [35:0] d_incoming ; + +// enable for incoming data register +reg d_incoming_ena ; + +// incoming data register control logic +always@(posedge wb_clock_in or posedge reset_in) +begin + if (reset_in) + d_incoming <= #`FF_DELAY {35{1'b0}} ; + else if (d_incoming_ena) + d_incoming <= #`FF_DELAY {SEL_I, SDATA_I} ; +end + +/*=================================================================================================================================================================================== +Write allow for image accesses. Writes through images are allowed when all of following are true: +- WBW_FIFO musn't be almost full nor full for image writes to be allowed - Every transaction takes at least two locations in the FIFO +- delayed read from from WISHBONE to PCI request musn't be present +- delayed read from PCI to WISHBONE completion musn't be present +- lock input musn't be set - it can be set because of error reporting or because PCI master state machine is disabled +===================================================================================================================================================================================*/ +wire wimg_wallow = ~|{ wbw_fifo_almost_full_in , wbw_fifo_full_in, wb_del_req_pending_in, pci_drcomp_pending_in, wbs_lock_in } ; +reg img_wallow ; +/*=================================================================================================================================================================================== +WISHBONE slave can request an image read accesses when all of following are true: +- delayed completion is not present +- delayed request is not present +- operation is not locked because of error reporting mechanism or because PCI master is disabled +===================================================================================================================================================================================*/ +wire wdo_del_request = ~|{ wb_del_req_pending_in, wb_del_comp_pending_in, wbs_lock_in } ; +reg do_del_request ; +/*=================================================================================================================================================================================== +WISHBONE slave can complete an image read accesses when all of following are true: +- delayed read completion is present +- delayed read completion is the same as current read access ( dread_completion_hit is 1 ) +- PCI Write FIFO is empty - no posted write is waiting to be finished in PCIW_FIFO +- WBR_FIFO empty status is not active +===================================================================================================================================================================================*/ +wire wdel_addr_hit = ( wb_del_addr_in == wb_addr_in ) && ( SEL_I == wb_del_be_in ) ; +reg del_addr_hit ; +wire wdel_completion_allow = wb_del_comp_pending_in && ((~del_write_in && ~WE_I && pciw_fifo_empty_in && ~wbr_fifo_empty_in) || (del_write_in && WE_I)) ; +reg del_completion_allow ; + +/*---------------------------------------------------------------------------------------------------------------------- +img_hit - state of wb_hit_in bus when when state machine signals decode is over +---------------------------------------------------------------------------------------------------------------------*/ +reg [4:0] img_hit ; +wire wb_hit = |( img_hit ) ; + +/*---------------------------------------------------------------------------------------------------------------------- +Control logic for image control signals +pref_en - prefetch enable of currently selected image +mrl_en - Memory read line enable of currently selected image +map - Address space mapping for currently selected image +---------------------------------------------------------------------------------------------------------------------*/ +reg pref_en, mrl_en, map ; +wire wpref_en = |(wb_pref_en_in & wb_hit_in) ; +wire wmrl_en = |(wb_mrl_en_in & wb_hit_in) ; +wire wmap = |(wb_map_in & wb_hit_in) ; + +// state machine controls when results from decoders, comparison etc. are sampled into registers to decode an access +reg decode_en ; + +reg wb_conf_hit ; +always@(posedge reset_in or posedge wb_clock_in) +begin + if (reset_in) + begin + img_wallow <= #`FF_DELAY 1'b0 ; + wb_conf_hit <= #`FF_DELAY 1'b0 ; + do_del_request <= #`FF_DELAY 1'b0 ; + del_addr_hit <= #`FF_DELAY 1'b0 ; + del_completion_allow <= #`FF_DELAY 1'b0 ; + img_hit <= #`FF_DELAY 5'h00 ; + pref_en <= #`FF_DELAY 1'b0 ; + mrl_en <= #`FF_DELAY 1'b0 ; + map <= #`FF_DELAY 1'b0 ; + end + else + if (decode_en) + begin + img_wallow <= #`FF_DELAY wimg_wallow ; + wb_conf_hit <= #`FF_DELAY wb_conf_hit_in ; + do_del_request <= #`FF_DELAY wdo_del_request ; + del_addr_hit <= #`FF_DELAY wdel_addr_hit ; + del_completion_allow <= #`FF_DELAY wdel_completion_allow ; + img_hit <= #`FF_DELAY wb_hit_in ; + pref_en <= #`FF_DELAY wpref_en && cache_line_size_not_zero ; + mrl_en <= #`FF_DELAY wmrl_en && cache_line_size_not_zero ; + map <= #`FF_DELAY wmap ; + end +end + +wire del_burst = CAB_I && (pref_en || mrl_en) && ~WE_I && cache_line_size_not_zero ; // delayed burst indicator - only when WB master attempts CAB transfer and cache line size register is set appropriately and + // either prefetch enable or memory read line enable of corresponding image are set - + // applies for reads only - delayed write cannot be a burst +wire do_dread_completion = del_completion_allow && del_addr_hit ; + +`ifdef GUEST + + // wires indicating allowance for configuration cycle generation requests + wire do_ccyc_req = 1'b0 ; + wire do_ccyc_comp = 1'b0 ; + + // wires indicating allowance for interrupt acknowledge cycle generation requests + wire do_iack_req = 1'b0 ; + wire do_iack_comp = 1'b0 ; + + // variables for configuration access control signals + reg conf_wenable ; + assign wb_conf_wenable_out = 1'b0 ; + + // configuration cycle data register hit + wire ccyc_hit = 1'b0 ; + wire iack_hit = 1'b0 ; + + wire wccyc_hit = 1'b0 ; + wire wiack_hit = 1'b0 ; + +`else +`ifdef HOST + // only host implementation has access for generating interrupt acknowledge and configuration cycles + // configuration cycle data register hit + reg current_delayed_is_ccyc ; + reg current_delayed_is_iack ; + + wire wccyc_hit = (wb_addr_in[8:2] == {1'b1, `CNF_DATA_ADDR}) ; + + wire wiack_hit = (wb_addr_in[8:2] == {1'b1, `INT_ACK_ADDR}) ; + + reg iack_hit ; + reg ccyc_hit ; + always@(posedge reset_in or posedge wb_clock_in) + begin + if (reset_in) + begin + ccyc_hit <= #`FF_DELAY 1'b0 ; + iack_hit <= #`FF_DELAY 1'b0 ; + end + else + if (decode_en) + begin + ccyc_hit <= #`FF_DELAY wccyc_hit ; + iack_hit <= #`FF_DELAY wiack_hit ; + end + end + + // wires indicating allowance for configuration cycle generation requests + wire do_ccyc_req = do_del_request && ccyc_hit; + wire do_ccyc_comp = del_completion_allow && ccyc_hit && current_delayed_is_ccyc ; // && del_bc_hit + + // wires indicating allowance for interrupt acknowledge cycle generation requests + wire do_iack_req = do_del_request && iack_hit ; + wire do_iack_comp = del_completion_allow && iack_hit && current_delayed_is_iack ; // && del_bc_hit + + // variables for configuration access control signals + reg conf_wenable ; + + // following flip-flops remember whether current delayed transaction is interrupt acknowledge or configuration cycle transaction + always@(posedge wb_clock_in or posedge reset_in) + begin + if ( reset_in ) + begin + current_delayed_is_ccyc <= #`FF_DELAY 1'b0 ; + current_delayed_is_iack <= #`FF_DELAY 1'b0 ; + end + else + if ( del_done_out ) + begin + current_delayed_is_ccyc <= #`FF_DELAY 1'b0 ; + current_delayed_is_iack <= #`FF_DELAY 1'b0 ; + end + else + if ( del_req_out && wb_conf_hit ) + begin + current_delayed_is_ccyc <= #`FF_DELAY do_ccyc_req ; + current_delayed_is_iack <= #`FF_DELAY do_iack_req ; + end + end + +`endif +`endif + +// configuration read enable - supplied for host and guest bridges +reg conf_renable ; +assign wb_conf_renable_out = conf_renable ; + +// burst access indicator +wire burst_transfer = CYC_I && CAB_I ; + +// WBW_FIFO control output +reg [3:0] wbw_fifo_control ; + +// WBW_FIFO wenable output assignment +reg wbw_fifo_wenable ; + +// WBR_FIFO control outputs +reg wbr_fifo_flush, wbr_fifo_renable ; // flush and read enable outputs + +// flush signal for WBR_FIFO must be registered, since it asinchronously resets some status registers +wire wbr_fifo_flush_reg ; +pci_async_reset_flop async_reset_as_wbr_flush +( + .data_in (wbr_fifo_flush), + .clk_in (wb_clock_in), + .async_reset_data_out (wbr_fifo_flush_reg), + .reset_in (reset_in) +) ; +assign wbr_fifo_flush_out = wbr_fifo_flush_reg ; + +// delayed transaction request control signals +reg del_req, del_done ; + +// WISHBONE handshaking control outputs +reg ack, rty, err ; + +`ifdef REGISTER_WBS_OUTPUTS +// wire for write attempt - 1 when external WB master is attempting a write +// wire for read attempt - 1 when external master is attempting a read +wire wattempt = ( CYC_I && STB_I && WE_I ) && (!ACK_O && !ERR_O && !RTY_O) ; +wire rattempt = ( CYC_I && STB_I && ~WE_I ) && (!ACK_O && !ERR_O && !RTY_O) ; + +`else +// wire for write attempt - 1 when external WB master is attempting a write +// wire for read attempt - 1 when external master is attempting a read +wire wattempt = ( CYC_I && STB_I && WE_I ) ; // write is qualified when cycle, strobe and write enable inputs are all high +wire rattempt = ( CYC_I && STB_I && ~WE_I ) ; // read is qualified when cycle and strobe are high and write enable is low + +`endif +/*---------------------------------------------------------------------------------------------------------------------- +Delayed transaction bus command generation +Bus command for delayed reads depends on image's address space mapping and control bits and +whether or not these are interrupt acknowledge requests or configuration cycle requests +---------------------------------------------------------------------------------------------------------------------*/ + +always@(map or mrl_en or ccyc_hit or WE_I or wb_conf_hit or CAB_I or pref_en) +begin +`ifdef HOST +// only host implementation supports configuration and interrupt acknowledge commands + if (wb_conf_hit) + begin + case( {ccyc_hit, WE_I} ) + 2'b11: del_bc = `BC_CONF_WRITE ; + 2'b10: del_bc = `BC_CONF_READ ; + 2'b01: del_bc = `BC_RESERVED0 ; // invalid combination - interrupt acknowledge cycle must be a read + 2'b00: del_bc = `BC_IACK ; + endcase + end + else +`endif + begin + if ( map ) + begin + del_bc = `BC_IO_READ ; + end + else + begin + case ({(CAB_I && mrl_en), pref_en}) + 2'b00: del_bc = `BC_MEM_READ ; // if this is not burst transfer or memory read line command is disabled - use memory read + 2'b01: del_bc = `BC_MEM_READ ; // same as previous case + 2'b10: del_bc = `BC_MEM_READ_LN ; // burst transfer, memory read line command enabled, prefetch disabled - use memory read line command + 2'b11: del_bc = `BC_MEM_READ_MUL ; // same as previous case, except prefetch is enabled - use memory read multiple command + endcase + end + end +end + +reg del_in_progress ; // state machine indicates whether current read completion is in progress on WISHBONE bus + +wire image_access_error = (map && burst_transfer) ; // IO write is a burst + +`ifdef HOST + reg [1:0] wbw_data_out_sel ; + parameter SEL_ADDR_IN = 2'b10 ; + parameter SEL_CCYC_ADDR = 2'b11 ; + parameter SEL_DATA_IN = 2'b00 ; +`else +`ifdef GUEST + reg wbw_data_out_sel ; + parameter SEL_ADDR_IN = 1'b1 ; + parameter SEL_DATA_IN = 1'b0 ; +`endif +`endif + +`ifdef WB_DECODE_FAST + `ifdef REGISTER_WBS_OUTPUTS + `define PCI_WB_SLAVE_S_DEC1 + `endif +`endif + +`ifdef WB_DECODE_MEDIUM + `define PCI_WB_SLAVE_S_DEC1 +`endif + +`ifdef WB_DECODE_SLOW + `define PCI_WB_SLAVE_S_DEC1 + `define PCI_WB_SLAVE_S_DEC2 +`endif +// state machine logic +always@( + c_state or + wattempt or + img_wallow or + burst_transfer or + wb_hit or + map or + rattempt or + do_dread_completion or + wbr_fifo_control_in or + wb_conf_hit or + do_ccyc_req or + do_ccyc_comp or + ccyc_hit or + del_error_in or + do_iack_req or + do_iack_comp or + iack_hit or + image_access_error or + wbw_fifo_almost_full_in or + wbw_fifo_full_in or + do_del_request or + wbr_fifo_empty_in or + init_complete_in + ) +begin + // default signal values + // response signals inactive + ack = 1'b0 ; + rty = 1'b0 ; + err = 1'b0 ; + + //write signals inactive + wbw_fifo_control[`ADDR_CTRL_BIT] = 1'b1 ; + wbw_fifo_control[`DATA_ERROR_CTRL_BIT] = 1'b0 ; + wbw_fifo_control[`LAST_CTRL_BIT] = 1'b0 ; + wbw_fifo_control[`UNUSED_CTRL_BIT] = 1'b0 ; + + wbw_fifo_wenable = 1'b0 ; + d_incoming_ena = 1'b0 ; + + // read signals inactive + wbr_fifo_flush = 1'b0 ; + wbr_fifo_renable = 1'b0 ; + del_req = 1'b0 ; + del_done = 1'b0 ; + + // configuration space control signals inactive + conf_wenable = 1'b0 ; + conf_renable = 1'b0 ; + + // read is not in progress + del_in_progress = 1'b0 ; + + decode_en = 1'b0 ; + + wbw_data_out_sel = SEL_ADDR_IN ; + + sample_address_out = 1'b0 ; + + case (c_state) + S_IDLE: begin + if ( (wattempt || rattempt) & init_complete_in ) + begin + + `ifdef PCI_WB_SLAVE_S_DEC1 + n_state = S_DEC1 ; + `else + decode_en = 1'b1 ; + n_state = S_START ; + `endif + + sample_address_out = 1'b1 ; + end + else + n_state = S_IDLE ; + end +`ifdef PCI_WB_SLAVE_S_DEC1 + S_DEC1: begin + if ( wattempt || rattempt ) + begin + + `ifdef PCI_WB_SLAVE_S_DEC2 + n_state = S_DEC2 ; + `else + decode_en = 1'b1 ; + n_state = S_START ; + `endif + + end + else + n_state = S_IDLE ; + end +`endif +`ifdef PCI_WB_SLAVE_S_DEC2 + S_DEC2: begin + + if ( wattempt || rattempt ) + begin + decode_en = 1'b1 ; + n_state = S_START ; + end + else + n_state = S_IDLE ; + end +`endif + S_START:begin + if (wb_conf_hit) // configuration space hit + begin + `ifdef HOST + wbw_data_out_sel = SEL_CCYC_ADDR ; + `endif + + if ( wattempt ) + n_state = S_CONF_WRITE ; // go to conf. write state + else + if ( rattempt ) + begin + n_state = S_CONF_READ ; // go to conf. read state + end + else + n_state = S_IDLE ; // master terminated - go back to idle state + + end // wb_conf_hit + else + if( wb_hit && (wattempt || rattempt) ) + begin + wbw_data_out_sel = SEL_DATA_IN ; + + // check error conditions for image writes or reads + if ( image_access_error ) + begin + n_state = S_IDLE ; // go back to idle state because of an error condition + err = 1'b1 ; + end // error conditions + else + // check for retry conditions for image writes or reads + if ( (wattempt && ~img_wallow) || + (rattempt && ~do_dread_completion) // write to image not allowed, no read ready yet - retry + ) + begin + n_state = S_IDLE ; // go back to IDLE + + rty = 1'b1 ; + + del_req = do_del_request && rattempt ; + + end //retry + else // everything OK - proceed + if ( wattempt ) + begin + n_state = S_W_ADDR_DATA ; // goto write transfer state + + // respond with acknowledge + ack = 1'b1 ; + + wbw_fifo_wenable = 1'b1 ; + + // data is latched to data incoming intermidiate stage - it will be put in FIFO later + d_incoming_ena = 1'b1 ; + end + else + begin + err = wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] ; + ack = ~wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] ; + wbr_fifo_renable = 1'b1 ; + del_in_progress = 1'b1 ; + + if ( wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] || wbr_fifo_control_in[`LAST_CTRL_BIT] ) + begin + + n_state = S_IDLE ; // go back to idle state + // respond that read is finished + del_done = 1'b1 ; + + end // end read + else + n_state = S_READ ; // go to read state + end + end + else + n_state = S_IDLE ; + + end + + S_W_ADDR_DATA: begin + wbw_data_out_sel = SEL_DATA_IN ; + err = 1'b0 ; + rty = burst_transfer && wattempt && (wbw_fifo_almost_full_in || wbw_fifo_full_in) ; + + if ( ~burst_transfer || wattempt && ( wbw_fifo_almost_full_in || wbw_fifo_full_in ) ) + begin + n_state = S_IDLE ; + + // write last data to FIFO and don't latch new data + wbw_fifo_control[`ADDR_CTRL_BIT] = 1'b0 ; + wbw_fifo_control[`LAST_CTRL_BIT] = 1'b1 ; + wbw_fifo_wenable = 1'b1 ; + end + else + begin + n_state = S_W_ADDR_DATA ; + wbw_fifo_control[`ADDR_CTRL_BIT] = 1'b0 ; + wbw_fifo_control[`LAST_CTRL_BIT] = 1'b0 ; + ack = wattempt ; + wbw_fifo_wenable = wattempt ; + d_incoming_ena = wattempt ; + end + end // S_W_ADDR_DATA + + S_READ:begin + // this state is for reads only - in this state read is in progress all the time + del_in_progress = 1'b1 ; + + ack = burst_transfer && rattempt && ~wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] && ~wbr_fifo_empty_in ; + err = burst_transfer && rattempt && wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] && ~wbr_fifo_empty_in ; + + // if acknowledge is beeing signalled then enable read from wbr fifo + wbr_fifo_renable = burst_transfer && rattempt && ~wbr_fifo_empty_in ; + + if ( ~burst_transfer || rattempt && (wbr_fifo_empty_in || wbr_fifo_control_in[`DATA_ERROR_CTRL_BIT] || wbr_fifo_control_in[`LAST_CTRL_BIT]) ) + begin + n_state = S_IDLE ; + del_done = 1'b1 ; + wbr_fifo_flush = ~wbr_fifo_empty_in ; + end + else + begin + n_state = S_READ ; + end + end // S_READ + + S_CONF_WRITE: begin + `ifdef HOST + wbw_data_out_sel = SEL_CCYC_ADDR ; + del_req = do_ccyc_req && ~burst_transfer ; + del_done = do_ccyc_comp && ~burst_transfer ; + del_in_progress = do_ccyc_comp && ~burst_transfer ; + `endif + + n_state = S_IDLE ; // next state after configuration access is always idle + + if ( burst_transfer ) + begin + err = 1'b1 ; + end + else + begin + `ifdef HOST + if ( do_ccyc_req || (ccyc_hit && ~do_ccyc_comp)) + begin + rty = 1'b1 ; + end + else + if ( do_ccyc_comp ) + begin + err = del_error_in ; + ack = ~del_error_in ; + end + else + begin + ack = ~ccyc_hit ; + conf_wenable = ~ccyc_hit ; + end + `else + ack = 1'b1 ; + conf_wenable = 1'b1 ; + `endif + end + end // S_CONF_WRITE + + S_CONF_READ: begin + `ifdef HOST + wbw_data_out_sel = SEL_CCYC_ADDR ; + del_req = ~burst_transfer && ( do_ccyc_req || do_iack_req ) ; + del_done = ~burst_transfer && ( do_ccyc_comp || do_iack_comp ) ; + del_in_progress = ~burst_transfer && ( do_ccyc_comp || do_iack_comp ) ; + wbr_fifo_renable = ~burst_transfer && ( do_ccyc_comp || do_iack_comp ) ; + `endif + + n_state = S_IDLE ; // next state after configuration access is always idle + + if ( burst_transfer ) + begin + err = 1'b1 ; + end + else + begin + `ifdef HOST + if ( do_ccyc_req || ( ccyc_hit && ~do_ccyc_comp )) + begin + rty = 1'b1 ; + end + else + if ( do_iack_req || ( iack_hit && ~do_iack_comp )) + begin + rty = 1'b1 ; + end + else + if ( do_iack_comp || do_ccyc_comp ) + begin + err = del_error_in ; + ack = ~del_error_in ; + end + else + begin + ack = ~( ccyc_hit || iack_hit ) ; + conf_renable = ~( ccyc_hit || iack_hit ) ; + end + `else + ack = 1'b1 ; + conf_renable = 1'b1 ; + `endif + end + end //S_CONF_READ + default:begin + n_state = S_IDLE ; // return to idle state + end //default + endcase +end + +// configuration space offset output assignment +assign wb_conf_offset_out = {wb_addr_in[11:2], 2'b00} ; // upper 10 bits of address input and two zeros + +// data output assignment - for image writes, first data is address, subsequent data comes from intermediate register +reg [31:0] wb_data ; +`ifdef HOST +reg [1:0] wbw_data_out_sel_reg ; +always@(posedge wb_clock_in or posedge reset_in) +begin + if ( reset_in ) + wbw_data_out_sel_reg <= #`FF_DELAY SEL_ADDR_IN ; + else + wbw_data_out_sel_reg <= #`FF_DELAY wbw_data_out_sel ; +end + +always@(wbw_data_out_sel_reg or wb_addr_in or ccyc_addr_in or d_incoming) +begin + case ( wbw_data_out_sel_reg ) + SEL_CCYC_ADDR: wb_data = ccyc_addr_in ; + SEL_DATA_IN: wb_data = d_incoming ; + default: wb_data = wb_addr_in ; + endcase +end +`else +`ifdef GUEST +reg wbw_data_out_sel_reg ; +always@(posedge wb_clock_in or posedge reset_in) +begin + if ( reset_in ) + wbw_data_out_sel_reg <= #`FF_DELAY SEL_ADDR_IN ; + else + wbw_data_out_sel_reg <= #`FF_DELAY wbw_data_out_sel ; +end + +always@(wbw_data_out_sel_reg or wb_addr_in or d_incoming) +begin + if ( wbw_data_out_sel_reg ) + wb_data = wb_addr_in ; + else + wb_data = d_incoming ; +end +`endif +`endif + +// command / byte enable assignment - with address, bus command is provided, with data - byte enables are provided +reg [3:0] wb_cbe ; + +always@(wbw_data_out_sel_reg or d_incoming or map) +begin + if (wbw_data_out_sel_reg && map) + wb_cbe = `BC_IO_WRITE ; + else + if (wbw_data_out_sel_reg) + wb_cbe = `BC_MEM_WRITE ; + else + wb_cbe = ~(d_incoming[35:32]) ; +end + +// for configuration writes, data output is always data from WISHBONE - in guest implementation data is all 0. +`ifdef GUEST + assign wb_conf_data_out = 32'h00000000 ; +`endif + +`ifdef GUEST + `ifdef NO_CNF_IMAGE + `else + `define PCI_WB_SLAVE_DO_OUT_MUX + `endif +`else +`ifdef HOST + `define PCI_WB_SLAVE_DO_OUT_MUX ; +`endif +`endif + +`ifdef PCI_WB_SLAVE_DO_OUT_MUX + reg [31:0] sdata_source ; + + // WISHBONE data output select lines for output multiplexor + wire sdata_o_sel_new = ( wb_conf_hit_in && ~wiack_hit && ~wccyc_hit ) ? CONF_SEL : WBR_SEL ; + reg sdata_o_sel ; + + always@(posedge wb_clock_in or posedge reset_in) + begin + if ( reset_in ) + sdata_o_sel <= #`FF_DELAY WBR_SEL ; + else + if ( decode_en ) + sdata_o_sel <= #`FF_DELAY sdata_o_sel_new ; + end + + always@(sdata_o_sel or wbr_fifo_data_in or wb_conf_data_in) + begin + case (sdata_o_sel) + WBR_SEL :sdata_source = wbr_fifo_data_in ; + CONF_SEL:sdata_source = wb_conf_data_in ; + endcase + end +`else + wire [31:0] sdata_source = wbr_fifo_data_in ; +`endif + +`ifdef REGISTER_WBS_OUTPUTS + +always@(posedge wb_clock_in or posedge reset_in) +begin + if ( reset_in ) + begin + ACK_O <= #`FF_DELAY 1'b0 ; + RTY_O <= #`FF_DELAY 1'b0 ; + ERR_O <= #`FF_DELAY 1'b0 ; + SDATA_O <= #`FF_DELAY 0 ; + del_write_out <= #`FF_DELAY 1'b0 ; + + `ifdef HOST + wb_conf_wenable_out <= #`FF_DELAY 1'b0 ; + wb_conf_data_out <= #`FF_DELAY 0 ; + `endif + + del_bc_out <= #`FF_DELAY `BC_RESERVED0 ; + del_req_out <= #`FF_DELAY 1'b0 ; + del_done_out <= #`FF_DELAY 1'b0 ; + del_burst_out <= #`FF_DELAY 1'b0 ; + del_in_progress_out <= #`FF_DELAY 1'b0 ; + wb_conf_be_out <= #`FF_DELAY 0 ; + wb_data_out <= #`FF_DELAY 0 ; + wb_cbe_out <= #`FF_DELAY 0 ; + wbw_fifo_wenable_out <= #`FF_DELAY 0 ; + wbw_fifo_control_out <= #`FF_DELAY 0 ; + wbr_fifo_renable_out <= #`FF_DELAY 0 ; + end + else + begin + ACK_O <= #`FF_DELAY ack && !ACK_O ; + RTY_O <= #`FF_DELAY rty && !RTY_O ; + ERR_O <= #`FF_DELAY err && !ERR_O ; + SDATA_O <= #`FF_DELAY sdata_source ; + del_write_out <= #`FF_DELAY WE_I ; + + `ifdef HOST + wb_conf_wenable_out <= #`FF_DELAY conf_wenable ; + wb_conf_data_out <= #`FF_DELAY SDATA_I ; + `endif + + del_bc_out <= #`FF_DELAY del_bc ; + del_req_out <= #`FF_DELAY del_req ; + del_done_out <= #`FF_DELAY del_done ; + del_burst_out <= #`FF_DELAY del_burst ; + del_in_progress_out <= #`FF_DELAY del_in_progress ; + wb_conf_be_out <= #`FF_DELAY SEL_I ; + wb_data_out <= #`FF_DELAY wb_data ; + wb_cbe_out <= #`FF_DELAY wb_cbe ; + wbw_fifo_wenable_out <= #`FF_DELAY wbw_fifo_wenable ; + wbw_fifo_control_out <= #`FF_DELAY wbw_fifo_control ; + wbr_fifo_renable_out <= #`FF_DELAY wbr_fifo_renable ; + end +end + +`else + +assign SDATA_O = sdata_source ; + +assign ACK_O = ack ; +assign RTY_O = rty ; +assign ERR_O = err ; + +// write operation indicator for delayed transaction requests +assign del_write_out = WE_I ; +assign del_bc_out = del_bc ; +assign del_req_out = del_req ; // read request +assign del_done_out = del_done ; // read done +assign del_burst_out = del_burst ; +assign del_in_progress_out = del_in_progress ; +`ifdef HOST +assign wb_conf_data_out = SDATA_I ; +assign wb_conf_wenable_out = conf_wenable ; +`endif +// Configuration space byte enables output +assign wb_conf_be_out = SEL_I ; // just route select lines from WISHBONE to conf space +assign wb_data_out = wb_data ; +assign wb_cbe_out = wb_cbe ; +assign wbw_fifo_wenable_out = wbw_fifo_wenable ; //write enable for WBW_FIFO +assign wbw_fifo_control_out = wbw_fifo_control ; //control bus output for WBW_FIFO +assign wbr_fifo_renable_out = wbr_fifo_renable ; //read enable for wbr_fifo +`endif + +endmodule //WB_SLAVE diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v new file mode 100644 index 000000000..cdba5b986 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v @@ -0,0 +1,876 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "wb_slave_unit.v" //// +//// //// +//// This file is part of the "PCI bridge" project //// +//// http://www.opencores.org/cores/pci/ //// +//// //// +//// Author(s): //// +//// - Miha Dolenc (mihad@opencores.org) //// +//// //// +//// All additional information is avaliable in the README //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_slave_unit.v,v $ +// Revision 1.3 2004/01/24 11:54:18 mihad +// Update! SPOCI Implemented! +// +// Revision 1.2 2003/10/17 09:11:52 markom +// mbist signals updated according to newest convention +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.8 2002/10/18 03:36:37 tadejm +// Changed wrong signal name mbist_sen into mbist_ctrl_i. +// +// Revision 1.7 2002/10/17 22:49:22 tadejm +// Changed BIST signals for RAMs. +// +// Revision 1.6 2002/10/11 10:09:01 mihad +// Added additional testcase and changed rst name in BIST to trst +// +// Revision 1.5 2002/10/08 17:17:06 mihad +// Added BIST signals for RAMs. +// +// Revision 1.4 2002/09/25 15:53:52 mihad +// Removed all logic from asynchronous reset network +// +// Revision 1.3 2002/02/01 15:25:13 mihad +// Repaired a few bugs, updated specification, added test bench files and design document +// +// Revision 1.2 2001/10/05 08:14:30 mihad +// Updated all files with inclusion of timescale file for simulation purposes. +// +// Revision 1.1.1.1 2001/10/02 15:33:46 mihad +// New project directory structure +// +// + +// Module instantiates and connects other modules lower in hierarcy +// Wishbone slave unit consists of modules that together form datapath +// between external WISHBONE masters and external PCI targets +`include "pci_constants.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module pci_wb_slave_unit +( + reset_in, + wb_clock_in, + pci_clock_in, + ADDR_I, + SDATA_I, + SDATA_O, + CYC_I, + STB_I, + WE_I, + SEL_I, + ACK_O, + RTY_O, + ERR_O, + CAB_I, + wbu_map_in, + wbu_pref_en_in, + wbu_mrl_en_in, + wbu_pci_drcomp_pending_in, + wbu_conf_data_in, + wbu_pciw_empty_in, + wbu_bar0_in, + wbu_bar1_in, + wbu_bar2_in, + wbu_bar3_in, + wbu_bar4_in, + wbu_bar5_in, + wbu_am0_in, + wbu_am1_in, + wbu_am2_in, + wbu_am3_in, + wbu_am4_in, + wbu_am5_in, + wbu_ta0_in, + wbu_ta1_in, + wbu_ta2_in, + wbu_ta3_in, + wbu_ta4_in, + wbu_ta5_in, + wbu_at_en_in, + wbu_ccyc_addr_in , + wbu_master_enable_in, + wb_init_complete_in, + wbu_cache_line_size_not_zero, + wbu_cache_line_size_in, + wbu_pciif_gnt_in, + wbu_pciif_frame_in, + wbu_pciif_irdy_in, + wbu_pciif_trdy_in, + wbu_pciif_trdy_reg_in, + wbu_pciif_stop_in, + wbu_pciif_stop_reg_in, + wbu_pciif_devsel_in, + wbu_pciif_devsel_reg_in, + wbu_pciif_ad_reg_in, + wbu_pciif_req_out, + wbu_pciif_frame_out, + wbu_pciif_frame_en_out, + wbu_pciif_frame_en_in, + wbu_pciif_frame_out_in, + wbu_pciif_frame_load_out, + wbu_pciif_irdy_out, + wbu_pciif_irdy_en_out, + wbu_pciif_ad_out, + wbu_pciif_ad_en_out, + wbu_pciif_cbe_out, + wbu_pciif_cbe_en_out, + wbu_err_addr_out, + wbu_err_bc_out, + wbu_err_signal_out, + wbu_err_source_out, + wbu_err_rty_exp_out, + wbu_tabort_rec_out, + wbu_mabort_rec_out, + wbu_conf_offset_out, + wbu_conf_renable_out, + wbu_conf_wenable_out, + wbu_conf_be_out, + wbu_conf_data_out, + wbu_del_read_comp_pending_out, + wbu_wbw_fifo_empty_out, + wbu_latency_tim_val_in, + wbu_ad_load_out, + wbu_ad_load_on_transfer_out + +`ifdef PCI_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif +); + +input reset_in, + wb_clock_in, + pci_clock_in ; + +input [31:0] ADDR_I ; +input [31:0] SDATA_I ; +output [31:0] SDATA_O ; +input CYC_I ; +input STB_I ; +input WE_I ; +input [3:0] SEL_I ; +output ACK_O ; +output RTY_O ; +output ERR_O ; +input CAB_I ; + +input [5:0] wbu_map_in ; +input [5:0] wbu_pref_en_in ; +input [5:0] wbu_mrl_en_in ; + +input wbu_pci_drcomp_pending_in ; + +input [31:0] wbu_conf_data_in ; + +input wbu_pciw_empty_in ; + +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_bar5_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_am5_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta0_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta1_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta2_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta3_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta4_in ; +input [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] wbu_ta5_in ; +input [5:0] wbu_at_en_in ; + +input [23:0] wbu_ccyc_addr_in ; + +input wbu_master_enable_in ; +input wb_init_complete_in ; + +input wbu_cache_line_size_not_zero ; +input [7:0] wbu_cache_line_size_in ; + +input wbu_pciif_gnt_in ; +input wbu_pciif_frame_in ; +input wbu_pciif_frame_en_in ; +input wbu_pciif_irdy_in ; +input wbu_pciif_trdy_in; +input wbu_pciif_trdy_reg_in; +input wbu_pciif_stop_in ; +input wbu_pciif_stop_reg_in ; +input wbu_pciif_devsel_in ; +input wbu_pciif_devsel_reg_in ; +input [31:0] wbu_pciif_ad_reg_in ; + +output wbu_pciif_req_out ; +output wbu_pciif_frame_out ; +output wbu_pciif_frame_en_out ; +input wbu_pciif_frame_out_in ; +output wbu_pciif_frame_load_out ; +output wbu_pciif_irdy_out ; +output wbu_pciif_irdy_en_out ; +output [31:0] wbu_pciif_ad_out ; +output wbu_pciif_ad_en_out ; +output [3:0] wbu_pciif_cbe_out ; +output wbu_pciif_cbe_en_out ; + +output [31:0] wbu_err_addr_out ; +output [3:0] wbu_err_bc_out ; +output wbu_err_signal_out ; +output wbu_err_source_out ; +output wbu_err_rty_exp_out ; +output wbu_tabort_rec_out ; +output wbu_mabort_rec_out ; + +output [11:0] wbu_conf_offset_out ; +output wbu_conf_renable_out ; +output wbu_conf_wenable_out ; +output [3:0] wbu_conf_be_out ; +output [31:0] wbu_conf_data_out ; + +output wbu_del_read_comp_pending_out ; +output wbu_wbw_fifo_empty_out ; + +input [7:0] wbu_latency_tim_val_in ; + +output wbu_ad_load_out ; +output wbu_ad_load_on_transfer_out ; + +`ifdef PCI_BIST +/*----------------------------------------------------- +BIST debug chain port signals +-----------------------------------------------------*/ +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +// pci master interface outputs +wire [31:0] pcim_if_address_out ; +wire [3:0] pcim_if_bc_out ; +wire [31:0] pcim_if_data_out ; +wire [3:0] pcim_if_be_out ; +wire pcim_if_req_out ; +wire pcim_if_rdy_out ; +wire pcim_if_last_out ; +wire pcim_if_wbw_renable_out ; +wire pcim_if_wbr_wenable_out ; +wire [31:0] pcim_if_wbr_data_out ; +wire [3:0] pcim_if_wbr_be_out ; +wire [3:0] pcim_if_wbr_control_out ; +wire pcim_if_del_complete_out ; +wire pcim_if_del_error_out ; +wire pcim_if_del_rty_exp_out ; +wire [31:0] pcim_if_err_addr_out ; +wire [3:0] pcim_if_err_bc_out ; +wire pcim_if_err_signal_out ; +wire pcim_if_err_source_out ; +wire pcim_if_err_rty_exp_out ; +wire pcim_if_tabort_out ; +wire pcim_if_mabort_out ; +wire [31:0] pcim_if_next_data_out ; +wire [3:0] pcim_if_next_be_out ; +wire pcim_if_next_last_out ; +wire pcim_if_posted_write_not_present_out ; + + + +wire pcim_sm_req_out ; +wire pcim_sm_frame_out ; +wire pcim_sm_frame_en_out ; +wire pcim_sm_irdy_out ; +wire pcim_sm_irdy_en_out ; +wire [31:0] pcim_sm_ad_out ; +wire pcim_sm_ad_en_out ; +wire [3:0] pcim_sm_cbe_out ; +wire pcim_sm_cbe_en_out ; +wire pcim_sm_ad_load_out ; +wire pcim_sm_ad_load_on_transfer_out ; + +wire pcim_sm_wait_out ; +wire pcim_sm_wtransfer_out ; +wire pcim_sm_rtransfer_out ; +wire pcim_sm_retry_out ; +wire pcim_sm_rerror_out ; +wire pcim_sm_first_out ; +wire pcim_sm_mabort_out ; +wire pcim_sm_frame_load_out ; + +assign wbu_pciif_frame_load_out = pcim_sm_frame_load_out ; + +assign wbu_err_addr_out = pcim_if_err_addr_out ; +assign wbu_err_bc_out = pcim_if_err_bc_out ; +assign wbu_err_signal_out = pcim_if_err_signal_out ; +assign wbu_err_source_out = pcim_if_err_source_out ; +assign wbu_err_rty_exp_out = pcim_if_err_rty_exp_out ; +assign wbu_tabort_rec_out = pcim_if_tabort_out ; +assign wbu_mabort_rec_out = pcim_if_mabort_out ; + +assign wbu_wbw_fifo_empty_out = pcim_if_posted_write_not_present_out ; + +// pci master state machine outputs +// pci interface signals +assign wbu_pciif_req_out = pcim_sm_req_out ; +assign wbu_pciif_frame_out = pcim_sm_frame_out ; +assign wbu_pciif_frame_en_out = pcim_sm_frame_en_out ; +assign wbu_pciif_irdy_out = pcim_sm_irdy_out ; +assign wbu_pciif_irdy_en_out = pcim_sm_irdy_en_out ; +assign wbu_pciif_ad_out = pcim_sm_ad_out ; +assign wbu_pciif_ad_en_out = pcim_sm_ad_en_out ; +assign wbu_pciif_cbe_out = pcim_sm_cbe_out ; +assign wbu_pciif_cbe_en_out = pcim_sm_cbe_en_out ; +assign wbu_ad_load_out = pcim_sm_ad_load_out ; +assign wbu_ad_load_on_transfer_out = pcim_sm_ad_load_on_transfer_out ; + +// signals to internal of the core +wire [31:0] pcim_sm_data_out ; + +// wishbone slave state machine outputs +wire [3:0] wbs_sm_del_bc_out ; +wire wbs_sm_del_req_out ; +wire wbs_sm_del_done_out ; +wire wbs_sm_del_burst_out ; +wire wbs_sm_del_write_out ; +wire [11:0] wbs_sm_conf_offset_out ; +wire wbs_sm_conf_renable_out ; +wire wbs_sm_conf_wenable_out ; +wire [3:0] wbs_sm_conf_be_out ; +wire [31:0] wbs_sm_conf_data_out ; +wire [31:0] wbs_sm_data_out ; +wire [3:0] wbs_sm_cbe_out ; +wire wbs_sm_wbw_wenable_out ; +wire [3:0] wbs_sm_wbw_control_out ; +wire wbs_sm_wbr_renable_out ; +wire wbs_sm_wbr_flush_out ; +wire wbs_sm_del_in_progress_out ; +wire [31:0] wbs_sm_sdata_out ; +wire wbs_sm_ack_out ; +wire wbs_sm_rty_out ; +wire wbs_sm_err_out ; +wire wbs_sm_sample_address_out ; + +assign wbu_conf_offset_out = wbs_sm_conf_offset_out ; +assign wbu_conf_renable_out = wbs_sm_conf_renable_out ; +assign wbu_conf_wenable_out = wbs_sm_conf_wenable_out ; +assign wbu_conf_be_out = ~wbs_sm_conf_be_out ; +assign wbu_conf_data_out = wbs_sm_conf_data_out ; + +assign SDATA_O = wbs_sm_sdata_out ; +assign ACK_O = wbs_sm_ack_out ; +assign RTY_O = wbs_sm_rty_out ; +assign ERR_O = wbs_sm_err_out ; + + +// wbw_wbr fifo outputs + +// wbw_fifo_outputs: +wire [31:0] fifos_wbw_addr_data_out ; +wire [3:0] fifos_wbw_cbe_out ; +wire [3:0] fifos_wbw_control_out ; +wire fifos_wbw_almost_full_out ; +wire fifos_wbw_full_out ; +wire fifos_wbw_empty_out ; +wire fifos_wbw_transaction_ready_out ; + +// wbr_fifo_outputs +wire [31:0] fifos_wbr_data_out ; +wire [3:0] fifos_wbr_be_out ; +wire [3:0] fifos_wbr_control_out ; +wire fifos_wbr_empty_out ; + +// address multiplexer outputs +wire [5:0] amux_hit_out ; +wire [31:0] amux_address_out ; + +// delayed transaction logic outputs +wire [31:0] del_sync_addr_out ; +wire [3:0] del_sync_be_out ; +wire del_sync_we_out ; +wire del_sync_comp_req_pending_out ; +wire del_sync_comp_comp_pending_out ; +wire del_sync_req_req_pending_out ; +wire del_sync_req_comp_pending_out ; +wire [3:0] del_sync_bc_out ; +wire del_sync_status_out ; +wire del_sync_comp_flush_out ; +wire del_sync_burst_out ; + +assign wbu_del_read_comp_pending_out = del_sync_comp_comp_pending_out ; + +// delayed write storage output +wire [31:0] del_write_data_out ; + +// config. cycle address decoder output +wire [31:0] ccyc_addr_out ; + + +// WISHBONE slave interface inputs +wire [4:0] wbs_sm_hit_in = amux_hit_out[5:1] ; +wire wbs_sm_conf_hit_in = amux_hit_out[0] ; +wire [4:0] wbs_sm_map_in = wbu_map_in[5:1] ; +wire [4:0] wbs_sm_pref_en_in = wbu_pref_en_in[5:1] ; +wire [4:0] wbs_sm_mrl_en_in = wbu_mrl_en_in[5:1] ; +wire [31:0] wbs_sm_addr_in = amux_address_out ; +wire [3:0] wbs_sm_del_bc_in = del_sync_bc_out ; +wire wbs_sm_del_req_pending_in = del_sync_req_req_pending_out ; +wire wbs_sm_wb_del_comp_pending_in = del_sync_req_comp_pending_out ; +wire wbs_sm_pci_drcomp_pending_in = wbu_pci_drcomp_pending_in ; +wire wbs_sm_del_write_in = del_sync_we_out ; +wire wbs_sm_del_error_in = del_sync_status_out ; +wire [31:0] wbs_sm_del_addr_in = del_sync_addr_out ; +wire [3:0] wbs_sm_del_be_in = del_sync_be_out ; +wire [31:0] wbs_sm_conf_data_in = wbu_conf_data_in ; +wire wbs_sm_wbw_almost_full_in = fifos_wbw_almost_full_out ; +wire wbs_sm_wbw_full_in = fifos_wbw_full_out ; +wire [3:0] wbs_sm_wbr_be_in = fifos_wbr_be_out ; +wire [31:0] wbs_sm_wbr_data_in = fifos_wbr_data_out ; +wire [3:0] wbs_sm_wbr_control_in = fifos_wbr_control_out ; +wire wbs_sm_wbr_empty_in = fifos_wbr_empty_out ; +wire wbs_sm_pciw_empty_in = wbu_pciw_empty_in ; +wire wbs_sm_lock_in = ~wbu_master_enable_in ; +wire wbs_sm_cache_line_size_not_zero = wbu_cache_line_size_not_zero ; +wire wbs_sm_cyc_in = CYC_I ; +wire wbs_sm_stb_in = STB_I ; +wire wbs_sm_we_in = WE_I ; +wire [3:0] wbs_sm_sel_in = SEL_I ; +wire [31:0] wbs_sm_sdata_in = SDATA_I ; +wire wbs_sm_cab_in = CAB_I ; +wire [31:0] wbs_sm_ccyc_addr_in = ccyc_addr_out ; +wire wbs_sm_init_complete_in = wb_init_complete_in ; + +// WISHBONE slave interface instantiation +pci_wb_slave wishbone_slave( + .wb_clock_in (wb_clock_in) , + .reset_in (reset_in) , + .wb_hit_in (wbs_sm_hit_in) , + .wb_conf_hit_in (wbs_sm_conf_hit_in) , + .wb_map_in (wbs_sm_map_in) , + .wb_pref_en_in (wbs_sm_pref_en_in) , + .wb_mrl_en_in (wbs_sm_mrl_en_in) , + .wb_addr_in (wbs_sm_addr_in), + .del_bc_in (wbs_sm_del_bc_in), + .wb_del_req_pending_in (wbs_sm_del_req_pending_in), + .wb_del_comp_pending_in (wbs_sm_wb_del_comp_pending_in), + .pci_drcomp_pending_in (wbs_sm_pci_drcomp_pending_in), + .del_bc_out (wbs_sm_del_bc_out), + .del_req_out (wbs_sm_del_req_out), + .del_done_out (wbs_sm_del_done_out), + .del_burst_out (wbs_sm_del_burst_out), + .del_write_out (wbs_sm_del_write_out), + .del_write_in (wbs_sm_del_write_in), + .del_error_in (wbs_sm_del_error_in), + .wb_del_addr_in (wbs_sm_del_addr_in), + .wb_del_be_in (wbs_sm_del_be_in), + .wb_conf_offset_out (wbs_sm_conf_offset_out), + .wb_conf_renable_out (wbs_sm_conf_renable_out), + .wb_conf_wenable_out (wbs_sm_conf_wenable_out), + .wb_conf_be_out (wbs_sm_conf_be_out), + .wb_conf_data_in (wbs_sm_conf_data_in), + .wb_conf_data_out (wbs_sm_conf_data_out), + .wb_data_out (wbs_sm_data_out), + .wb_cbe_out (wbs_sm_cbe_out), + .wbw_fifo_wenable_out (wbs_sm_wbw_wenable_out), + .wbw_fifo_control_out (wbs_sm_wbw_control_out), + .wbw_fifo_almost_full_in (wbs_sm_wbw_almost_full_in), + .wbw_fifo_full_in (wbs_sm_wbw_full_in), + .wbr_fifo_renable_out (wbs_sm_wbr_renable_out), + .wbr_fifo_be_in (wbs_sm_wbr_be_in), + .wbr_fifo_data_in (wbs_sm_wbr_data_in), + .wbr_fifo_control_in (wbs_sm_wbr_control_in), + .wbr_fifo_flush_out (wbs_sm_wbr_flush_out), + .wbr_fifo_empty_in (wbs_sm_wbr_empty_in), + .pciw_fifo_empty_in (wbs_sm_pciw_empty_in), + .wbs_lock_in (wbs_sm_lock_in), + .init_complete_in (wbs_sm_init_complete_in), + .cache_line_size_not_zero (wbs_sm_cache_line_size_not_zero), + .del_in_progress_out (wbs_sm_del_in_progress_out), + .ccyc_addr_in (wbs_sm_ccyc_addr_in), + .sample_address_out (wbs_sm_sample_address_out), + .CYC_I (wbs_sm_cyc_in), + .STB_I (wbs_sm_stb_in), + .WE_I (wbs_sm_we_in), + .SEL_I (wbs_sm_sel_in), + .SDATA_I (wbs_sm_sdata_in), + .SDATA_O (wbs_sm_sdata_out), + .ACK_O (wbs_sm_ack_out), + .RTY_O (wbs_sm_rty_out), + .ERR_O (wbs_sm_err_out), + .CAB_I (wbs_sm_cab_in) + ); + +// wbw_wbr_fifos inputs +// WBW_FIFO inputs +wire fifos_wbw_wenable_in = wbs_sm_wbw_wenable_out; +wire [31:0] fifos_wbw_addr_data_in = wbs_sm_data_out ; +wire [3:0] fifos_wbw_cbe_in = wbs_sm_cbe_out ; +wire [3:0] fifos_wbw_control_in = wbs_sm_wbw_control_out ; +wire fifos_wbw_renable_in = pcim_if_wbw_renable_out ; + +//wire fifos_wbw_flush_in = 1'b0 ; flush for write fifo not used + +// WBR_FIFO inputs +wire fifos_wbr_wenable_in = pcim_if_wbr_wenable_out ; +wire [31:0] fifos_wbr_data_in = pcim_if_wbr_data_out ; +wire [3:0] fifos_wbr_be_in = pcim_if_wbr_be_out ; +wire [3:0] fifos_wbr_control_in = pcim_if_wbr_control_out ; +wire fifos_wbr_renable_in = wbs_sm_wbr_renable_out ; +wire fifos_wbr_flush_in = wbs_sm_wbr_flush_out || del_sync_comp_flush_out ; + +// WBW_FIFO and WBR_FIFO instantiation +pci_wbw_wbr_fifos fifos +( + .wb_clock_in (wb_clock_in), + .pci_clock_in (pci_clock_in), + .reset_in (reset_in), + .wbw_wenable_in (fifos_wbw_wenable_in), + .wbw_addr_data_in (fifos_wbw_addr_data_in), + .wbw_cbe_in (fifos_wbw_cbe_in), + .wbw_control_in (fifos_wbw_control_in), + .wbw_renable_in (fifos_wbw_renable_in), + .wbw_addr_data_out (fifos_wbw_addr_data_out), + .wbw_cbe_out (fifos_wbw_cbe_out), + .wbw_control_out (fifos_wbw_control_out), +// .wbw_flush_in (fifos_wbw_flush_in), // flush for write fifo not used + .wbw_almost_full_out (fifos_wbw_almost_full_out), + .wbw_full_out (fifos_wbw_full_out), + .wbw_empty_out (fifos_wbw_empty_out), + .wbw_transaction_ready_out (fifos_wbw_transaction_ready_out), + .wbr_wenable_in (fifos_wbr_wenable_in), + .wbr_data_in (fifos_wbr_data_in), + .wbr_be_in (fifos_wbr_be_in), + .wbr_control_in (fifos_wbr_control_in), + .wbr_renable_in (fifos_wbr_renable_in), + .wbr_data_out (fifos_wbr_data_out), + .wbr_be_out (fifos_wbr_be_out), + .wbr_control_out (fifos_wbr_control_out), + .wbr_flush_in (fifos_wbr_flush_in), + .wbr_empty_out (fifos_wbr_empty_out) + +`ifdef PCI_BIST + , + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) +`endif +) ; + +wire [31:0] amux_addr_in = ADDR_I ; +wire amux_sample_address_in = wbs_sm_sample_address_out ; + +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar0_in = wbu_bar0_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar1_in = wbu_bar1_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar2_in = wbu_bar2_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar3_in = wbu_bar3_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar4_in = wbu_bar4_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_bar5_in = wbu_bar5_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am0_in = wbu_am0_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am1_in = wbu_am1_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am2_in = wbu_am2_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am3_in = wbu_am3_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am4_in = wbu_am4_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_am5_in = wbu_am5_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta0_in = wbu_ta0_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta1_in = wbu_ta1_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta2_in = wbu_ta2_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta3_in = wbu_ta3_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta4_in = wbu_ta4_in ; +wire [(`WB_NUM_OF_DEC_ADDR_LINES - 1):0] amux_ta5_in = wbu_ta5_in ; +wire [5:0] amux_at_en_in = wbu_at_en_in ; + +pci_wb_addr_mux wb_addr_dec +( + `ifdef REGISTER_WBS_OUTPUTS + .clk_in (wb_clock_in), + .reset_in (reset_in), + .sample_address_in (amux_sample_address_in), + `endif + .address_in (amux_addr_in), + .bar0_in (amux_bar0_in), + .bar1_in (amux_bar1_in), + .bar2_in (amux_bar2_in), + .bar3_in (amux_bar3_in), + .bar4_in (amux_bar4_in), + .bar5_in (amux_bar5_in), + .am0_in (amux_am0_in), + .am1_in (amux_am1_in), + .am2_in (amux_am2_in), + .am3_in (amux_am3_in), + .am4_in (amux_am4_in), + .am5_in (amux_am5_in), + .ta0_in (amux_ta0_in), + .ta1_in (amux_ta1_in), + .ta2_in (amux_ta2_in), + .ta3_in (amux_ta3_in), + .ta4_in (amux_ta4_in), + .ta5_in (amux_ta5_in), + .at_en_in (amux_at_en_in), + .hit_out (amux_hit_out), + .address_out (amux_address_out) +); + +// delayed transaction logic inputs +wire del_sync_req_in = wbs_sm_del_req_out ; +wire del_sync_comp_in = pcim_if_del_complete_out ; +wire del_sync_done_in = wbs_sm_del_done_out ; +wire del_sync_in_progress_in = wbs_sm_del_in_progress_out ; +wire [31:0] del_sync_addr_in = wbs_sm_data_out ; +wire [3:0] del_sync_be_in = wbs_sm_conf_be_out ; +wire del_sync_we_in = wbs_sm_del_write_out ; +wire [3:0] del_sync_bc_in = wbs_sm_del_bc_out ; +wire del_sync_status_in = pcim_if_del_error_out ; +wire del_sync_burst_in = wbs_sm_del_burst_out ; +wire del_sync_retry_expired_in = pcim_if_del_rty_exp_out ; + +// delayed transaction logic instantiation +pci_delayed_sync del_sync ( + .reset_in (reset_in), + .req_clk_in (wb_clock_in), + .comp_clk_in (pci_clock_in), + .req_in (del_sync_req_in), + .comp_in (del_sync_comp_in), + .done_in (del_sync_done_in), + .in_progress_in (del_sync_in_progress_in), + .comp_req_pending_out (del_sync_comp_req_pending_out), + .comp_comp_pending_out(del_sync_comp_comp_pending_out), + .req_req_pending_out (del_sync_req_req_pending_out), + .req_comp_pending_out (del_sync_req_comp_pending_out), + .addr_in (del_sync_addr_in), + .be_in (del_sync_be_in), + .addr_out (del_sync_addr_out), + .be_out (del_sync_be_out), + .we_in (del_sync_we_in), + .we_out (del_sync_we_out), + .bc_in (del_sync_bc_in), + .bc_out (del_sync_bc_out), + .status_in (del_sync_status_in), + .status_out (del_sync_status_out), + .comp_flush_out (del_sync_comp_flush_out), + .burst_in (del_sync_burst_in), + .burst_out (del_sync_burst_out), + .retry_expired_in (del_sync_retry_expired_in) + ); + +// delayed write storage inputs +wire del_write_we_in = wbs_sm_del_req_out && wbs_sm_del_write_out ; +wire [31:0] del_write_data_in = wbs_sm_conf_data_out ; + +pci_delayed_write_reg delayed_write_data +( + .reset_in (reset_in), + .req_clk_in (wb_clock_in), + .comp_wdata_out (del_write_data_out), + .req_we_in (del_write_we_in), + .req_wdata_in (del_write_data_in) +); + +`ifdef HOST + // configuration cycle address decoder input + wire [31:0] ccyc_addr_in = {8'h00, wbu_ccyc_addr_in} ; + + pci_conf_cyc_addr_dec ccyc_addr_dec + ( + .ccyc_addr_in (ccyc_addr_in), + .ccyc_addr_out (ccyc_addr_out) + ) ; +`else +`ifdef GUEST + assign ccyc_addr_out = 32'h0000_0000 ; +`endif +`endif + +// pci master interface inputs +wire [31:0] pcim_if_wbw_addr_data_in = fifos_wbw_addr_data_out ; +wire [3:0] pcim_if_wbw_cbe_in = fifos_wbw_cbe_out ; +wire [3:0] pcim_if_wbw_control_in = fifos_wbw_control_out ; +wire pcim_if_wbw_empty_in = fifos_wbw_empty_out ; +wire pcim_if_wbw_transaction_ready_in = fifos_wbw_transaction_ready_out ; +wire [31:0] pcim_if_data_in = pcim_sm_data_out ; +wire [31:0] pcim_if_del_wdata_in = del_write_data_out ; +wire pcim_if_del_req_in = del_sync_comp_req_pending_out ; +wire [31:0] pcim_if_del_addr_in = del_sync_addr_out ; +wire [3:0] pcim_if_del_bc_in = del_sync_bc_out ; +wire [3:0] pcim_if_del_be_in = del_sync_be_out ; +wire pcim_if_del_burst_in = del_sync_burst_out ; +wire pcim_if_del_we_in = del_sync_we_out ; +wire [7:0] pcim_if_cache_line_size_in = wbu_cache_line_size_in ; +wire pcim_if_wait_in = pcim_sm_wait_out ; +wire pcim_if_wtransfer_in = pcim_sm_wtransfer_out ; +wire pcim_if_rtransfer_in = pcim_sm_rtransfer_out ; +wire pcim_if_retry_in = pcim_sm_retry_out ; +wire pcim_if_rerror_in = pcim_sm_rerror_out ; +wire pcim_if_first_in = pcim_sm_first_out ; +wire pcim_if_mabort_in = pcim_sm_mabort_out ; + +pci_master32_sm_if pci_initiator_if +( + .clk_in (pci_clock_in), + .reset_in (reset_in), + .address_out (pcim_if_address_out), + .bc_out (pcim_if_bc_out), + .data_out (pcim_if_data_out), + .data_in (pcim_if_data_in), + .be_out (pcim_if_be_out), + .req_out (pcim_if_req_out), + .rdy_out (pcim_if_rdy_out), + .last_out (pcim_if_last_out), + .wbw_renable_out (pcim_if_wbw_renable_out), + .wbw_fifo_addr_data_in (pcim_if_wbw_addr_data_in), + .wbw_fifo_cbe_in (pcim_if_wbw_cbe_in), + .wbw_fifo_control_in (pcim_if_wbw_control_in), + .wbw_fifo_empty_in (pcim_if_wbw_empty_in), + .wbw_fifo_transaction_ready_in (pcim_if_wbw_transaction_ready_in), + .wbr_fifo_wenable_out (pcim_if_wbr_wenable_out), + .wbr_fifo_data_out (pcim_if_wbr_data_out), + .wbr_fifo_be_out (pcim_if_wbr_be_out), + .wbr_fifo_control_out (pcim_if_wbr_control_out), + .del_wdata_in (pcim_if_del_wdata_in), + .del_complete_out (pcim_if_del_complete_out), + .del_req_in (pcim_if_del_req_in), + .del_addr_in (pcim_if_del_addr_in), + .del_bc_in (pcim_if_del_bc_in), + .del_be_in (pcim_if_del_be_in), + .del_burst_in (pcim_if_del_burst_in), + .del_error_out (pcim_if_del_error_out), + .del_rty_exp_out (pcim_if_del_rty_exp_out), + .del_we_in (pcim_if_del_we_in), + .err_addr_out (pcim_if_err_addr_out), + .err_bc_out (pcim_if_err_bc_out), + .err_signal_out (pcim_if_err_signal_out), + .err_source_out (pcim_if_err_source_out), + .err_rty_exp_out (pcim_if_err_rty_exp_out), + .cache_line_size_in (pcim_if_cache_line_size_in), + .mabort_received_out (pcim_if_mabort_out), + .tabort_received_out (pcim_if_tabort_out), + .next_data_out (pcim_if_next_data_out), + .next_be_out (pcim_if_next_be_out), + .next_last_out (pcim_if_next_last_out), + .wait_in (pcim_if_wait_in), + .wtransfer_in (pcim_if_wtransfer_in), + .rtransfer_in (pcim_if_rtransfer_in), + .retry_in (pcim_if_retry_in), + .rerror_in (pcim_if_rerror_in), + .first_in (pcim_if_first_in), + .mabort_in (pcim_if_mabort_in), + .posted_write_not_present_out (pcim_if_posted_write_not_present_out) +); + +// pci master state machine inputs +wire pcim_sm_gnt_in = wbu_pciif_gnt_in ; +wire pcim_sm_frame_in = wbu_pciif_frame_in ; +wire pcim_sm_irdy_in = wbu_pciif_irdy_in ; +wire pcim_sm_trdy_in = wbu_pciif_trdy_in; +wire pcim_sm_stop_in = wbu_pciif_stop_in ; +wire pcim_sm_devsel_in = wbu_pciif_devsel_in ; +wire [31:0] pcim_sm_ad_reg_in = wbu_pciif_ad_reg_in ; +wire [31:0] pcim_sm_address_in = pcim_if_address_out ; +wire [3:0] pcim_sm_bc_in = pcim_if_bc_out ; +wire [31:0] pcim_sm_data_in = pcim_if_data_out ; +wire [3:0] pcim_sm_be_in = pcim_if_be_out ; +wire pcim_sm_req_in = pcim_if_req_out ; +wire pcim_sm_rdy_in = pcim_if_rdy_out ; +wire pcim_sm_last_in = pcim_if_last_out ; +wire [7:0] pcim_sm_latency_tim_val_in = wbu_latency_tim_val_in ; +wire [31:0] pcim_sm_next_data_in = pcim_if_next_data_out ; +wire [3:0] pcim_sm_next_be_in = pcim_if_next_be_out ; +wire pcim_sm_next_last_in = pcim_if_next_last_out ; +wire pcim_sm_trdy_reg_in = wbu_pciif_trdy_reg_in ; +wire pcim_sm_stop_reg_in = wbu_pciif_stop_reg_in ; +wire pcim_sm_devsel_reg_in = wbu_pciif_devsel_reg_in ; +wire pcim_sm_frame_en_in = wbu_pciif_frame_en_in ; +wire pcim_sm_frame_out_in = wbu_pciif_frame_out_in ; + +pci_master32_sm pci_initiator_sm +( + .clk_in (pci_clock_in), + .reset_in (reset_in), + .pci_req_out (pcim_sm_req_out), + .pci_gnt_in (pcim_sm_gnt_in), + .pci_frame_in (pcim_sm_frame_in), + .pci_frame_out (pcim_sm_frame_out), + .pci_frame_en_out (pcim_sm_frame_en_out), + .pci_frame_out_in (pcim_sm_frame_out_in), + .pci_frame_load_out (pcim_sm_frame_load_out), + .pci_frame_en_in (pcim_sm_frame_en_in), + .pci_irdy_in (pcim_sm_irdy_in), + .pci_irdy_out (pcim_sm_irdy_out), + .pci_irdy_en_out (pcim_sm_irdy_en_out), + .pci_trdy_in (pcim_sm_trdy_in), + .pci_trdy_reg_in (pcim_sm_trdy_reg_in), + .pci_stop_in (pcim_sm_stop_in), + .pci_stop_reg_in (pcim_sm_stop_reg_in), + .pci_devsel_in (pcim_sm_devsel_in), + .pci_devsel_reg_in (pcim_sm_devsel_reg_in), + .pci_ad_reg_in (pcim_sm_ad_reg_in), + .pci_ad_out (pcim_sm_ad_out), + .pci_ad_en_out (pcim_sm_ad_en_out), + .pci_cbe_out (pcim_sm_cbe_out), + .pci_cbe_en_out (pcim_sm_cbe_en_out), + .address_in (pcim_sm_address_in), + .bc_in (pcim_sm_bc_in), + .data_in (pcim_sm_data_in), + .data_out (pcim_sm_data_out), + .be_in (pcim_sm_be_in), + .req_in (pcim_sm_req_in), + .rdy_in (pcim_sm_rdy_in), + .last_in (pcim_sm_last_in), + .latency_tim_val_in (pcim_sm_latency_tim_val_in), + .next_data_in (pcim_sm_next_data_in), + .next_be_in (pcim_sm_next_be_in), + .next_last_in (pcim_sm_next_last_in), + .ad_load_out (pcim_sm_ad_load_out), + .ad_load_on_transfer_out (pcim_sm_ad_load_on_transfer_out), + .wait_out (pcim_sm_wait_out), + .wtransfer_out (pcim_sm_wtransfer_out), + .rtransfer_out (pcim_sm_rtransfer_out), + .retry_out (pcim_sm_retry_out), + .rerror_out (pcim_sm_rerror_out), + .first_out (pcim_sm_first_out), + .mabort_out (pcim_sm_mabort_out) +) ; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v new file mode 100644 index 000000000..bd4667b7f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v @@ -0,0 +1,465 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Generic Two-Port Synchronous RAM //// +//// //// +//// This file is part of pci bridge project //// +//// http://www.opencores.org/cvsweb.shtml/pci/ //// +//// //// +//// Description //// +//// This block is a wrapper with common two-port //// +//// synchronous memory interface for different //// +//// types of ASIC and FPGA RAMs. Beside universal memory //// +//// interface it also provides behavioral model of generic //// +//// two-port synchronous RAM. //// +//// It should be used in all OPENCORES designs that want to be //// +//// portable accross different target technologies and //// +//// independent of target memory. //// +//// //// +//// Supported ASIC RAMs are: //// +//// - Artisan Double-Port Sync RAM //// +//// - Avant! Two-Port Sync RAM (*) //// +//// - Virage 2-port Sync RAM //// +//// //// +//// Supported FPGA RAMs are: //// +//// - Xilinx Virtex RAMB4_S16_S16 //// +//// //// +//// To Do: //// +//// - fix Avant! //// +//// - xilinx rams need external tri-state logic //// +//// - add additional RAMs (Altera, VS etc) //// +//// //// +//// Author(s): //// +//// - Damjan Lampret, lampret@opencores.org //// +//// - Miha Dolenc, mihad@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: pci_wb_tpram.v,v $ +// Revision 1.4 2004/08/19 15:27:34 mihad +// Changed minimum pci image size to 256 bytes because +// of some PC system problems with size of IO images. +// +// Revision 1.3 2003/10/17 09:11:52 markom +// mbist signals updated according to newest convention +// +// Revision 1.2 2003/08/14 13:06:03 simons +// synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. +// +// Revision 1.1 2003/01/27 16:49:31 mihad +// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. +// +// Revision 1.7 2002/10/18 03:36:37 tadejm +// Changed wrong signal name mbist_sen into mbist_ctrl_i. +// +// Revision 1.6 2002/10/17 22:49:22 tadejm +// Changed BIST signals for RAMs. +// +// Revision 1.5 2002/10/11 10:09:01 mihad +// Added additional testcase and changed rst name in BIST to trst +// +// Revision 1.4 2002/10/08 17:17:06 mihad +// Added BIST signals for RAMs. +// +// Revision 1.3 2002/09/30 17:22:27 mihad +// Added support for Virtual Silicon two port RAM. Didn't run regression on it yet! +// +// Revision 1.2 2002/08/19 16:51:36 mihad +// Extracted distributed RAM module from wb/pci_tpram.v to its own file, got rid of undef directives +// +// Revision 1.1 2002/02/01 14:43:31 mihad +// *** empty log message *** +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`include "pci_constants.v" + +module pci_wb_tpram +( + // Generic synchronous two-port RAM interface + clk_a, + rst_a, + ce_a, + we_a, + oe_a, + addr_a, + di_a, + do_a, + clk_b, + rst_b, + ce_b, + we_b, + oe_b, + addr_b, + di_b, + do_b +`ifdef PCI_BIST + , + // debug chain signals + mbist_si_i, // bist scan serial in + mbist_so_o, // bist scan serial out + mbist_ctrl_i // bist chain shift control +`endif +); + +// +// Default address and data buses width +// +parameter aw = 8; +parameter dw = 40; + +// +// Generic synchronous two-port RAM interface +// +input clk_a; // Clock +input rst_a; // Reset +input ce_a; // Chip enable input +input we_a; // Write enable input +input oe_a; // Output enable input +input [aw-1:0] addr_a; // address bus inputs +input [dw-1:0] di_a; // input data bus +output [dw-1:0] do_a; // output data bus +input clk_b; // Clock +input rst_b; // Reset +input ce_b; // Chip enable input +input we_b; // Write enable input +input oe_b; // Output enable input +input [aw-1:0] addr_b; // address bus inputs +input [dw-1:0] di_b; // input data bus +output [dw-1:0] do_b; // output data bus + +`ifdef PCI_BIST +// debug chain signals +input mbist_si_i; // bist scan serial in +output mbist_so_o; // bist scan serial out +input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control +`endif + +// +// Internal wires and registers +// + +`ifdef WB_VS_STP + `define PCI_WB_RAM_SELECTED + `ifdef PCI_BIST + vs_hdtp_64x40_bist i_vs_hdtp_64x40_bist + `else + vs_hdtp_64x40 i_vs_hdtp_64x40 + `endif + ( + .RCK (clk_b), + .WCK (clk_a), + .RADR (addr_b), + .WADR (addr_a), + .DI (di_a), + .DOUT (do_b), + .REN (1'b0), + .WEN (!we_a) + `ifdef PCI_BIST + , + // debug chain signals + .mbist_si_i (mbist_si_i), + .mbist_so_o (mbist_so_o), + .mbist_ctrl_i (mbist_ctrl_i) + `endif + ); + + assign do_a = 0 ; +`endif + +`ifdef WB_ARTISAN_SDP + `define PCI_WB_RAM_SELECTED + // + // Instantiation of ASIC memory: + // + // Artisan Synchronous Double-Port RAM (ra2sh) + // + `ifdef PCI_BIST + art_hsdp_64x40_bist /*#(dw, 1<= StepLockOut) then + + StepCounter <= "00000000000000000000000000000000"; -- if we just roll-ed over, then it's time to do something + + if (ProvideStaticHolding = '1') then --should we leave coils in energized state by defaul or not? + + StepDrive <= "0000"; + + else + + StepDrive <= "1111"; + + end if; + + if (InternalStepEnable = '1') then -- are we supposed to step on this clock? + + InternalStepEnable <= StepEnable; -- InternalStepEnable togles at the speed of the clock divider rollover, trailing the + -- external StepEnable by less than or equal to one rollover. + -- Putting this inside the "if internal=1" makes us wait until after move to turn off, + -- so we move at least once for each pulse of external step enable line. + + if (Direction = '1') then state <= state + "01"; end if; -- to change the direction of a stepper motor, you energize + if (Direction = '0') then state <= state - "01"; end if; -- the coils in the opposite pattern, so just run states backwards + -- this also allows a change of direction at any arbitrary point + case state is + + when "00" => + + StepDrive <= "1010"; -- these states follow proper pattern of coil energizing for turning steppers + + when "01" => + + StepDrive <= "1001"; + + when "10" => + + StepDrive <= "0101"; + + when "11" => + + StepDrive <= "0110"; + + when others => + + end case; --state + + end if; + + end if; + + end if; + + end process; + +end StepDrive; diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v new file mode 100644 index 000000000..e5021ed16 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v @@ -0,0 +1,358 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// AES top file //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// AES top //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: aes.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module aes(clk,reset,load_i,decrypt_i,data_i,key_i,ready_o,data_o); +input clk; +input reset; +input load_i; +input decrypt_i; +input [127:0] data_i; +input [127:0] key_i; +output ready_o; +output [127:0] data_o; + +reg ready_o; +reg [127:0] data_o; + +reg next_ready_o; +reg keysched_start_i; +reg [3:0] keysched_round_i; +reg [127:0] keysched_last_key_i; +wire [127:0] keysched_new_key_o; + +wire keysched_ready_o; + +wire keysched_sbox_access_o; + +wire [7:0] keysched_sbox_data_o; + +wire keysched_sbox_decrypt_o; + +reg mixcol_start_i; +reg [127:0] mixcol_data_i; +wire mixcol_ready_o; + +wire [127:0] mixcol_data_o; + +reg subbytes_start_i; +reg [127:0] subbytes_data_i; +wire subbytes_ready_o; + +wire [127:0] subbytes_data_o; + +wire [7:0] subbytes_sbox_data_o; + +wire subbytes_sbox_decrypt_o; + +wire [7:0] sbox_data_o; + +reg [7:0] sbox_data_i; +reg sbox_decrypt_i; +reg state; +reg next_state; +reg [3:0] round; +reg [3:0] next_round; +reg [127:0] addroundkey_data_o; +reg [127:0] next_addroundkey_data_reg; +reg [127:0] addroundkey_data_reg; +reg [127:0] addroundkey_data_i; +reg addroundkey_ready_o; +reg next_addroundkey_ready_o; +reg addroundkey_start_i; +reg next_addroundkey_start_i; +reg [3:0] addroundkey_round; +reg [3:0] next_addroundkey_round; +reg first_round_reg; +reg next_first_round_reg; + +sbox sbox1 (.clk(clk), .reset(reset), .data_i(sbox_data_i), .decrypt_i(sbox_decrypt_i), .data_o(sbox_data_o)); +subbytes sub1 (.clk(clk), .reset(reset), .start_i(subbytes_start_i), .decrypt_i(decrypt_i), .data_i(subbytes_data_i), .ready_o(subbytes_ready_o), .data_o(subbytes_data_o), .sbox_data_o(subbytes_sbox_data_o), .sbox_data_i(sbox_data_o), .sbox_decrypt_o(subbytes_sbox_decrypt_o)); +mixcolum mix1 (.clk(clk), .reset(reset), .decrypt_i(decrypt_i), .start_i(mixcol_start_i), .data_i(mixcol_data_i), .ready_o(mixcol_ready_o), .data_o(mixcol_data_o)); +keysched ks1 (.clk(clk), .reset(reset), .start_i(keysched_start_i), .round_i(keysched_round_i), .last_key_i(keysched_last_key_i), .new_key_o(keysched_new_key_o), .ready_o(keysched_ready_o), .sbox_access_o(keysched_sbox_access_o), .sbox_data_o(keysched_sbox_data_o), .sbox_data_i(sbox_data_o), .sbox_decrypt_o(keysched_sbox_decrypt_o)); + +//registers: +always @(posedge clk or negedge reset) + +begin + + if(!reset) +begin + + state = (0); + ready_o = (0); + round = (0); + addroundkey_round = (0); + addroundkey_data_reg = (0); + addroundkey_ready_o = (0); + addroundkey_start_i = (0); + first_round_reg = (0); + +end +else +begin + + state = (next_state); + ready_o = (next_ready_o); + round = (next_round); + addroundkey_round = (next_addroundkey_round); + addroundkey_data_reg = (next_addroundkey_data_reg); + addroundkey_ready_o = (next_addroundkey_ready_o); + first_round_reg = (next_first_round_reg); + addroundkey_start_i = (next_addroundkey_start_i); + +end + + +end +//control: +always @( state or round or addroundkey_data_o or data_i or load_i or decrypt_i or addroundkey_ready_o or mixcol_ready_o or subbytes_ready_o or subbytes_data_o or mixcol_data_o or first_round_reg) + +begin + + + next_state = (state); + next_round = (round); + data_o = (addroundkey_data_o); + next_ready_o = (0); + + //Tokeyschedulemodule + + next_first_round_reg = (0); + + + subbytes_data_i = (0); + mixcol_data_i = (0); + addroundkey_data_i = (0); + next_addroundkey_start_i = (first_round_reg); + mixcol_start_i = ((addroundkey_ready_o&decrypt_i&round!=10)|(subbytes_ready_o&!decrypt_i)); + subbytes_start_i = ((addroundkey_ready_o&!decrypt_i)|(mixcol_ready_o&decrypt_i)|(addroundkey_ready_o&decrypt_i&round==10)); + + if(decrypt_i&&round!=10) + begin + addroundkey_data_i = (subbytes_data_o); + subbytes_data_i = (mixcol_data_o); + mixcol_data_i = (addroundkey_data_o); + end + else if(!decrypt_i&&round!=0) + begin + addroundkey_data_i = (mixcol_data_o); + subbytes_data_i = (addroundkey_data_o); + mixcol_data_i = (subbytes_data_o); + end + else + begin + mixcol_data_i = (subbytes_data_o); + subbytes_data_i = (addroundkey_data_o); + addroundkey_data_i = (data_i); + end + + + case(state) + + 0: + begin + if(load_i) + begin + next_state = (1); + if(decrypt_i) + next_round = (10); + else + next_round = (0); + next_first_round_reg = (1); + end + end + + 1: + begin + + //Counter + if(!decrypt_i&&mixcol_ready_o) + begin + next_addroundkey_start_i = (1); + addroundkey_data_i = (mixcol_data_o); + next_round = (round+1); + end + else if(decrypt_i&&subbytes_ready_o) + begin + next_addroundkey_start_i = (1); + addroundkey_data_i = (subbytes_data_o); + next_round = (round-1); + end + + //Output + if((round==9&&!decrypt_i)||(round==0&&decrypt_i)) + begin + next_addroundkey_start_i = (0); + mixcol_start_i = (0); + if(subbytes_ready_o) + begin + addroundkey_data_i = (subbytes_data_o); + next_addroundkey_start_i = (1); + next_round = (round+1); + end + end + + if((round==10&&!decrypt_i)||(round==0&&decrypt_i)) + begin + addroundkey_data_i = (subbytes_data_o); + subbytes_start_i = (0); + if(addroundkey_ready_o) + begin + next_ready_o = (1); + next_state = (0); + next_addroundkey_start_i = (0); + next_round = (0); + end + + end + + + end + + default: +begin + next_state = (0); + end + endcase + + +end +//addroundkey: +reg[127:0] data_var,round_data_var,round_key_var; +always @( addroundkey_data_i or addroundkey_start_i or addroundkey_data_reg or addroundkey_round or keysched_new_key_o or keysched_ready_o or key_i or round) + +begin + + + + round_data_var=addroundkey_data_reg; + next_addroundkey_data_reg = (addroundkey_data_reg); +next_addroundkey_ready_o = (0); + next_addroundkey_round = (addroundkey_round); + addroundkey_data_o = (addroundkey_data_reg); + + if(addroundkey_round==1||addroundkey_round==0) + keysched_last_key_i = (key_i); +else + keysched_last_key_i = (keysched_new_key_o); + + keysched_start_i = (0); + + keysched_round_i = (addroundkey_round); + + if(round==0&&addroundkey_start_i) +begin + + //Taketheinputandxorthemwithdataifround==0; + data_var=addroundkey_data_i; + round_key_var=key_i; + round_data_var=round_key_var^data_var; + next_addroundkey_data_reg = (round_data_var); +next_addroundkey_ready_o = (1); + +end +else if(addroundkey_start_i&&round!=0) +begin + + keysched_last_key_i = (key_i); + keysched_start_i = (1); + keysched_round_i = (1); + next_addroundkey_round = (1); + +end +else if(addroundkey_round!=round&&keysched_ready_o) +begin + +next_addroundkey_round = (addroundkey_round+1); + keysched_last_key_i = (keysched_new_key_o); + keysched_start_i = (1); + keysched_round_i = (addroundkey_round+1); + +end +else if(addroundkey_round==round&&keysched_ready_o) +begin + + data_var=addroundkey_data_i; + round_key_var=keysched_new_key_o; + round_data_var=round_key_var^data_var; + next_addroundkey_data_reg = (round_data_var); +next_addroundkey_ready_o = (1); + next_addroundkey_round = (0); + +end + + +end +//sbox_muxes: +always @( keysched_sbox_access_o or keysched_sbox_decrypt_o or keysched_sbox_data_o or subbytes_sbox_decrypt_o or subbytes_sbox_data_o) + +begin + + + if(keysched_sbox_access_o) +begin + + sbox_decrypt_i = (keysched_sbox_decrypt_o); + sbox_data_i = (keysched_sbox_data_o); + +end +else +begin + + sbox_decrypt_i = (subbytes_sbox_decrypt_o); +sbox_data_i = (subbytes_sbox_data_o); + +end + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v new file mode 100644 index 000000000..b248cc400 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v @@ -0,0 +1,92 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns for 8 bit //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum for a byte //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: byte_mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module byte_mixcolum(a,b,c,d,outx,outy); + +input [7:0] a,b,c,d; +output [7:0] outx, outy; + +reg [7:0] outx, outy; + +function [7:0] xtime; +input [7:0] in; +reg [3:0] xtime_t; + +begin +xtime[7:5] = in[6:4]; +xtime_t[3] = in[7]; +xtime_t[2] = in[7]; +xtime_t[1] = 0; +xtime_t[0] = in[7]; +xtime[4:1] =xtime_t^in[3:0]; +xtime[0] = in[7]; +end +endfunction + +reg [7:0] w1,w2,w3,w4,w5,w6,w7,w8,outx_var; +always @ (a, b, c, d) +begin +w1 = a ^b; +w2 = a ^c; +w3 = c ^d; +w4 = xtime(w1); +w5 = xtime(w3); +w6 = w2 ^w4 ^w5; +w7 = xtime(w6); +w8 = xtime(w7); + +outx_var = b^w3^w4; +outx=outx_var; +outy=w8^outx_var; + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v new file mode 100644 index 000000000..f242c5675 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v @@ -0,0 +1,248 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Key schedule //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Generate the next round key from the previous one //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: keysched.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module keysched(clk,reset,start_i,round_i,last_key_i,new_key_o,ready_o,sbox_access_o,sbox_data_o,sbox_data_i,sbox_decrypt_o); +input clk; +input reset; +input start_i; +input [3:0] round_i; +input [127:0] last_key_i; +output [127:0] new_key_o; +output ready_o; +output sbox_access_o; +output [7:0] sbox_data_o; +input [7:0] sbox_data_i; +output sbox_decrypt_o; + +reg [127:0] new_key_o; +reg ready_o; +reg sbox_access_o; +reg [7:0] sbox_data_o; +reg sbox_decrypt_o; + +reg [2:0] next_state; +reg [2:0] state; +reg [7:0] rcon_o; +reg [31:0] next_col; +reg [31:0] col; +reg [127:0] key_reg; +reg [127:0] next_key_reg; +reg next_ready_o; + + +//rcon: +always @( round_i) + +begin + + + case(round_i) + 1: +begin +rcon_o = (1); +end + 2: +begin +rcon_o = (2); +end + 3: +begin +rcon_o = (4); +end + 4: +begin +rcon_o = (8); +end + 5: +begin +rcon_o = ('h10); +end + 6: +begin +rcon_o = ('h20); +end + 7: +begin +rcon_o = ('h40); +end + 8: +begin +rcon_o = ('h80); +end + 9: +begin +rcon_o = ('h1B); +end + 10: +begin +rcon_o = ('h36); +end +default: +begin + rcon_o = (0); +end + endcase + + +end +//registers: +always @(posedge clk or negedge reset) + +begin + + if(!reset) + begin + state = (0); + col = (0); + key_reg = (0); + ready_o = (0); + end +else + begin + state = (next_state); + col = (next_col); + key_reg = (next_key_reg); + ready_o = (next_ready_o); + end + + +end +//generate_key: +reg[127:0] K_var,W_var; + reg[31:0] col_t; + reg[23:0] zero; + +always @( start_i or last_key_i or sbox_data_i or state or rcon_o or col or key_reg) + +begin + + + zero=0; + + col_t=col; + W_var=0; + + next_state = (state); + next_col = (col); + + next_ready_o = (0); + next_key_reg = (key_reg); + new_key_o = (key_reg); + +sbox_decrypt_o = (0); + sbox_access_o = (0); + sbox_data_o = (0); + K_var=last_key_i; + + case(state) + //Substitutethebyteswhilerotatingthem + //FouraccessestoSBoxareneeded + 0: +begin + if(start_i) +begin + + col_t=0; + sbox_access_o = (1); + sbox_data_o = (K_var[31:24]); + next_state = (1); + +end + + end + 1: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[23:16]); + col_t[7:0]=sbox_data_i; + next_col = (col_t); + next_state = (2); + end + 2: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[15:8]); + col_t[31:24]=sbox_data_i; + next_col = (col_t); + next_state = (3); + end + 3: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[7:0]); + col_t[23:16]=sbox_data_i; + next_col = (col_t); + next_state = (4); + end + 4: +begin + sbox_access_o = (1); + col_t[15:8]=sbox_data_i; + next_col = (col_t); + W_var[127:96]=col_t^K_var[127:96]^{rcon_o,zero}; + W_var[95:64]=W_var[127:96]^K_var[95:64]; + W_var[63:32]=W_var[95:64]^K_var[63:32]; + W_var[31:0]=W_var[63:32]^K_var[31:0]; +next_ready_o = (1); +next_key_reg = (W_var); + next_state = (0); + end + +default: +begin + next_state = (0); + end +endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v new file mode 100644 index 000000000..ab6dc1e67 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v @@ -0,0 +1,188 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum module //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + + +module mixcolum(clk,reset,decrypt_i,start_i,data_i,ready_o,data_o); +input clk; +input reset; +input decrypt_i; +input start_i; +input [127:0] data_i; +output ready_o; +output [127:0] data_o; + +reg ready_o; +reg [127:0] data_o; + +reg [127:0] data_reg; +reg [127:0] next_data_reg; +reg [127:0] data_o_reg; +reg [127:0] next_data_o; +reg next_ready_o; +reg [1:0] state; +reg [1:0] next_state; +wire [31:0] outx; + +wire [31:0] outy; + +reg [31:0] mix_word; +reg [31:0] outmux; + +word_mixcolum w1 (.in(mix_word), .outx(outx), .outy(outy)); + +//assign_data_o: +always @( data_o_reg) + +begin + + data_o = (data_o_reg); + +end +//mux: +always @( outx or outy or decrypt_i) + +begin + + outmux = (decrypt_i?outy:outx); + +end +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) + begin + data_reg = (0); + state = (0); + ready_o = (0); + data_o_reg = (0); + end +else + begin + data_reg = (next_data_reg); + state = (next_state); + ready_o = (next_ready_o); + data_o_reg = (next_data_o); + end + + +end +//mixcol: +reg[127:0] data_i_var; + reg[31:0] aux; + reg[127:0] data_reg_var; + +always @( decrypt_i or start_i or state or data_reg or outmux or data_o_reg or data_i) + +begin + + + data_i_var=data_i; + data_reg_var=data_reg; + next_data_reg = (data_reg); + next_state = (state); + + mix_word = (0); + + next_ready_o = (0); + next_data_o = (data_o_reg); + + case(state) + + 0: +begin + if(start_i) +begin + + aux=data_i_var[127:96]; + mix_word = (aux); + data_reg_var[127:96]=outmux; + next_data_reg = (data_reg_var); + next_state = (1); + +end + + end + 1: +begin + aux=data_i_var[95:64]; + mix_word = (aux); + data_reg_var[95:64]=outmux; + next_data_reg = (data_reg_var); + next_state = (2); + end + 2: +begin + aux=data_i_var[63:32]; + mix_word = (aux); + data_reg_var[63:32]=outmux; + next_data_reg = (data_reg_var); + next_state = (3); + end + 3: +begin + aux=data_i_var[31:0]; + mix_word = (aux); + data_reg_var[31:0]=outmux; + next_data_o = (data_reg_var); + next_ready_o = (1); + next_state = (0); + end + default: + begin + end + endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v new file mode 100644 index 000000000..b5f741c30 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v @@ -0,0 +1,392 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// S-Box calculation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// S-box calculation calculating inverse on gallois field //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: sbox.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module sbox(clk,reset,data_i,decrypt_i,data_o); +input clk; +input reset; +input [7:0] data_i; +input decrypt_i; +output [7:0] data_o; + +reg [7:0] data_o; + +reg [7:0] inva; +reg [3:0] ah; +reg [3:0] al; +reg [3:0] ah2; +reg [3:0] al2; +reg [3:0] alxh; +reg [3:0] alph; +reg [3:0] d; +reg [3:0] ahp; +reg [3:0] alp; +reg [3:0] to_invert; +reg [3:0] next_to_invert; +reg [3:0] ah_reg; +reg [3:0] next_ah_reg; +reg [3:0] next_alph; + + +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) +begin + +to_invert = (0); + ah_reg = (0); +alph = (0); + +end +else +begin + + to_invert = (next_to_invert); + ah_reg = (next_ah_reg); +alph = (next_alph); + +end + + +end +//first_mux: +reg[7:0] first_mux_data_var; + reg[7:0] first_mux_InvInput; + reg[3:0] first_mux_ah_t,first_mux_al_t; + reg first_mux_aA,first_mux_aB,first_mux_aC,first_mux_aD; + +always @( data_i or decrypt_i) + +begin + + + first_mux_data_var=data_i; + first_mux_InvInput=first_mux_data_var; + + case(decrypt_i) + 1: +begin + //Applyinverseaffinetrasformation +first_mux_aA=first_mux_data_var[0]^first_mux_data_var[5];first_mux_aB=first_mux_data_var[1]^first_mux_data_var[4]; + first_mux_aC=first_mux_data_var[2]^first_mux_data_var[7];first_mux_aD=first_mux_data_var[3]^first_mux_data_var[6]; + first_mux_InvInput[0]=(!first_mux_data_var[5])^first_mux_aC; + first_mux_InvInput[1]=first_mux_data_var[0]^first_mux_aD; + first_mux_InvInput[2]=(!first_mux_data_var[7])^first_mux_aB; + first_mux_InvInput[3]=first_mux_data_var[2]^first_mux_aA; + first_mux_InvInput[4]=first_mux_data_var[1]^first_mux_aD; + first_mux_InvInput[5]=first_mux_data_var[4]^first_mux_aC; + first_mux_InvInput[6]=first_mux_data_var[3]^first_mux_aA; + first_mux_InvInput[7]=first_mux_data_var[6]^first_mux_aB; + end + default: +begin +first_mux_InvInput=first_mux_data_var; + end + endcase + + + //ConvertelementsfromGF(2^8)intotwoelementsofGF(2^4^2) + + first_mux_aA=first_mux_InvInput[1]^first_mux_InvInput[7]; + first_mux_aB=first_mux_InvInput[5]^first_mux_InvInput[7]; + first_mux_aC=first_mux_InvInput[4]^first_mux_InvInput[6]; + + + first_mux_al_t[0]=first_mux_aC^first_mux_InvInput[0]^first_mux_InvInput[5]; + first_mux_al_t[1]=first_mux_InvInput[1]^first_mux_InvInput[2]; + first_mux_al_t[2]=first_mux_aA; + first_mux_al_t[3]=first_mux_InvInput[2]^first_mux_InvInput[4]; + + first_mux_ah_t[0]=first_mux_aC^first_mux_InvInput[5]; + first_mux_ah_t[1]=first_mux_aA^first_mux_aC; + first_mux_ah_t[2]=first_mux_aB^first_mux_InvInput[2]^first_mux_InvInput[3]; + first_mux_ah_t[3]=first_mux_aB; + + al = (first_mux_al_t); + ah = (first_mux_ah_t); + next_ah_reg = (first_mux_ah_t); + +end +//end_mux: +reg[7:0] end_mux_data_var,end_mux_data_o_var; + reg end_mux_aA,end_mux_aB,end_mux_aC,end_mux_aD; + +always @( decrypt_i or inva) + +begin + + + + //Taketheoutputoftheinverter + end_mux_data_var=inva; + + case(decrypt_i) + 0: +begin + //Applyaffinetrasformation +end_mux_aA=end_mux_data_var[0]^end_mux_data_var[1];end_mux_aB=end_mux_data_var[2]^end_mux_data_var[3]; + end_mux_aC=end_mux_data_var[4]^end_mux_data_var[5];end_mux_aD=end_mux_data_var[6]^end_mux_data_var[7]; + end_mux_data_o_var[0]=(!end_mux_data_var[0])^end_mux_aC^end_mux_aD; + end_mux_data_o_var[1]=(!end_mux_data_var[5])^end_mux_aA^end_mux_aD; + end_mux_data_o_var[2]=end_mux_data_var[2]^end_mux_aA^end_mux_aD; + end_mux_data_o_var[3]=end_mux_data_var[7]^end_mux_aA^end_mux_aB; + end_mux_data_o_var[4]=end_mux_data_var[4]^end_mux_aA^end_mux_aB; + end_mux_data_o_var[5]=(!end_mux_data_var[1])^end_mux_aB^end_mux_aC; + end_mux_data_o_var[6]=(!end_mux_data_var[6])^end_mux_aB^end_mux_aC; + end_mux_data_o_var[7]=end_mux_data_var[3]^end_mux_aC^end_mux_aD; + data_o = (end_mux_data_o_var); + end + default: +begin +data_o = (end_mux_data_var); + end + endcase + + + +end +//inversemap: +reg[3:0] aA,aB; + reg[3:0] inversemap_alp_t,inversemap_ahp_t; + reg[7:0] inversemap_inva_t; + +always @( alp or ahp) +begin + + + inversemap_alp_t=alp; + inversemap_ahp_t=ahp; + + aA=inversemap_alp_t[1]^inversemap_ahp_t[3]; + aB=inversemap_ahp_t[0]^inversemap_ahp_t[1]; + + inversemap_inva_t[0]=inversemap_alp_t[0]^inversemap_ahp_t[0]; + inversemap_inva_t[1]=aB^inversemap_ahp_t[3]; + inversemap_inva_t[2]=aA^aB; + inversemap_inva_t[3]=aB^inversemap_alp_t[1]^inversemap_ahp_t[2]; + inversemap_inva_t[4]=aA^aB^inversemap_alp_t[3]; + inversemap_inva_t[5]=aB^inversemap_alp_t[2]; + inversemap_inva_t[6]=aA^inversemap_alp_t[2]^inversemap_alp_t[3]^inversemap_ahp_t[0]; + inversemap_inva_t[7]=aB^inversemap_alp_t[2]^inversemap_ahp_t[3]; + + inva = (inversemap_inva_t); + +end +//mul1: +reg[3:0] mul1_alxh_t; + reg[3:0] mul1_aA,mul1_a; + +always @( ah or al) + +begin + + //alxah + + mul1_aA=al[0]^al[3]; + mul1_a=al[2]^al[3]; + + mul1_alxh_t[0]=(al[0]&ah[0])^(al[3]&ah[1])^(al[2]&ah[2])^(al[1]&ah[3]); + mul1_alxh_t[1]=(al[1]&ah[0])^(mul1_aA&ah[1])^(mul1_a&ah[2])^((al[1]^al[2])&ah[3]); + mul1_alxh_t[2]=(al[2]&ah[0])^(al[1]&ah[1])^(mul1_aA&ah[2])^(mul1_a&ah[3]); + mul1_alxh_t[3]=(al[3]&ah[0])^(al[2]&ah[1])^(al[1]&ah[2])^(mul1_aA&ah[3]); + + alxh = (mul1_alxh_t); + +end +//mul2: +reg[3:0] mul2_ahp_t; + reg[3:0] mul2_aA,mul2_aB; + +always @( d or ah_reg) + +begin + + //ahxd + + mul2_aA=ah_reg[0]^ah_reg[3]; + mul2_aB=ah_reg[2]^ah_reg[3]; + + mul2_ahp_t[0]=(ah_reg[0]&d[0])^(ah_reg[3]&d[1])^(ah_reg[2]&d[2])^(ah_reg[1]&d[3]); + mul2_ahp_t[1]=(ah_reg[1]&d[0])^(mul2_aA&d[1])^(mul2_aB&d[2])^((ah_reg[1]^ah_reg[2])&d[3]); + mul2_ahp_t[2]=(ah_reg[2]&d[0])^(ah_reg[1]&d[1])^(mul2_aA&d[2])^(mul2_aB&d[3]); + mul2_ahp_t[3]=(ah_reg[3]&d[0])^(ah_reg[2]&d[1])^(ah_reg[1]&d[2])^(mul2_aA&d[3]); + + ahp = (mul2_ahp_t); + +end +//mul3: +reg[3:0] mul3_alp_t; + reg[3:0] mul3_aA,mul3_aB; + +always @( d or alph) + +begin + + //dxal + + mul3_aA=d[0]^d[3]; + mul3_aB=d[2]^d[3]; + + mul3_alp_t[0]=(d[0]&alph[0])^(d[3]&alph[1])^(d[2]&alph[2])^(d[1]&alph[3]); + mul3_alp_t[1]=(d[1]&alph[0])^(mul3_aA&alph[1])^(mul3_aB&alph[2])^((d[1]^d[2])&alph[3]); + mul3_alp_t[2]=(d[2]&alph[0])^(d[1]&alph[1])^(mul3_aA&alph[2])^(mul3_aB&alph[3]); + mul3_alp_t[3]=(d[3]&alph[0])^(d[2]&alph[1])^(d[1]&alph[2])^(mul3_aA&alph[3]); + + alp = (mul3_alp_t); + +end +//intermediate: +reg[3:0] intermediate_aA,intermediate_aB; + reg[3:0] intermediate_ah2e,intermediate_ah2epl2,intermediate_to_invert_var; + +always @( ah2 or al2 or alxh) + +begin + + + //ahsquareismultipliedwithe + intermediate_aA=ah2[0]^ah2[1]; + intermediate_aB=ah2[2]^ah2[3]; + intermediate_ah2e[0]=ah2[1]^intermediate_aB; + intermediate_ah2e[1]=intermediate_aA; + intermediate_ah2e[2]=intermediate_aA^ah2[2]; + intermediate_ah2e[3]=intermediate_aA^intermediate_aB; + + //Additionofintermediate_ah2eplusal2 + intermediate_ah2epl2[0]=intermediate_ah2e[0]^al2[0]; + intermediate_ah2epl2[1]=intermediate_ah2e[1]^al2[1]; + intermediate_ah2epl2[2]=intermediate_ah2e[2]^al2[2]; + intermediate_ah2epl2[3]=intermediate_ah2e[3]^al2[3]; + + //Additionoflastresultwiththeresultof(alxah) + intermediate_to_invert_var[0]=intermediate_ah2epl2[0]^alxh[0]; + intermediate_to_invert_var[1]=intermediate_ah2epl2[1]^alxh[1]; + intermediate_to_invert_var[2]=intermediate_ah2epl2[2]^alxh[2]; + intermediate_to_invert_var[3]=intermediate_ah2epl2[3]^alxh[3]; + +//Registers + next_to_invert = (intermediate_to_invert_var); + +end +//inversion: +reg[3:0] inversion_to_invert_var; + reg[3:0] inversion_aA,inversion_d_t; + +always @( to_invert) + +begin + + + inversion_to_invert_var=to_invert; + + //InverttheresultinGF(2^4) + inversion_aA=inversion_to_invert_var[1]^inversion_to_invert_var[2]^inversion_to_invert_var[3]^(inversion_to_invert_var[1]&inversion_to_invert_var[2]&inversion_to_invert_var[3]); + inversion_d_t[0]=inversion_aA^inversion_to_invert_var[0]^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^(inversion_to_invert_var[1]&inversion_to_invert_var[2])^(inversion_to_invert_var[0]&inversion_to_invert_var[1]&inversion_to_invert_var[2]); + inversion_d_t[1]=(inversion_to_invert_var[0]&inversion_to_invert_var[1])^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^(inversion_to_invert_var[1]&inversion_to_invert_var[2])^inversion_to_invert_var[3]^(inversion_to_invert_var[1]&inversion_to_invert_var[3])^(inversion_to_invert_var[0]&inversion_to_invert_var[1]&inversion_to_invert_var[3]); + inversion_d_t[2]=(inversion_to_invert_var[0]&inversion_to_invert_var[1])^inversion_to_invert_var[2]^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^inversion_to_invert_var[3]^(inversion_to_invert_var[0]&inversion_to_invert_var[3])^(inversion_to_invert_var[0]&inversion_to_invert_var[2]&inversion_to_invert_var[3]); + inversion_d_t[3]=inversion_aA^(inversion_to_invert_var[0]&inversion_to_invert_var[3])^(inversion_to_invert_var[1]&inversion_to_invert_var[3])^(inversion_to_invert_var[2]&inversion_to_invert_var[3]); + + d = (inversion_d_t); + + +end +//sum1: +reg[3:0] sum1_alph_t; + +always @( ah or al) + +begin + + + sum1_alph_t[0]=al[0]^ah[0]; + sum1_alph_t[1]=al[1]^ah[1]; + sum1_alph_t[2]=al[2]^ah[2]; + sum1_alph_t[3]=al[3]^ah[3]; + + next_alph = (sum1_alph_t); + +end +//square1: +reg[3:0] square1_ah_t; + +always @( ah) + +begin + + + square1_ah_t[0]=ah[0]^ah[2]; + square1_ah_t[1]=ah[2]; + square1_ah_t[2]=ah[1]^ah[3]; + square1_ah_t[3]=ah[3]; + + ah2 = (square1_ah_t); + +end +//square2: +reg[3:0] square2_al_t; + +always @( al) + +begin + + + square2_al_t[0]=al[0]^al[2]; + square2_al_t[1]=al[2]; + square2_al_t[2]=al[1]^al[3]; + square2_al_t[3]=al[3]; + + al2 = (square2_al_t); + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v new file mode 100644 index 000000000..eb0470bfe --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v @@ -0,0 +1,254 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Subbytes module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Subbytes module implementation //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: subbytes.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module subbytes(clk,reset,start_i,decrypt_i,data_i,ready_o,data_o,sbox_data_o,sbox_data_i,sbox_decrypt_o); +input clk; +input reset; +input start_i; +input decrypt_i; +input [127:0] data_i; +output ready_o; +output [127:0] data_o; +output [7:0] sbox_data_o; +input [7:0] sbox_data_i; +output sbox_decrypt_o; + +reg ready_o; +reg [127:0] data_o; +reg [7:0] sbox_data_o; +reg sbox_decrypt_o; + +reg [4:0] state; +reg [4:0] next_state; +reg [127:0] data_reg; +reg [127:0] next_data_reg; +reg next_ready_o; + +`define assign_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[1]; \ + data_reg_128[111:104]=data_reg_var[2]; \ + data_reg_128[103:96]=data_reg_var[3]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[5]; \ + data_reg_128[79:72]=data_reg_var[6]; \ + data_reg_128[71:64]=data_reg_var[7]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[9]; \ + data_reg_128[47:40]=data_reg_var[10]; \ + data_reg_128[39:32]=data_reg_var[11]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[13]; \ + data_reg_128[15:8]=data_reg_var[14]; \ + data_reg_128[7:0]=data_reg_var[15]; + +`define shift_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[5]; \ + data_reg_128[111:104]=data_reg_var[10]; \ + data_reg_128[103:96]=data_reg_var[15]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[9]; \ + data_reg_128[79:72]=data_reg_var[14]; \ + data_reg_128[71:64]=data_reg_var[3]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[13]; \ + data_reg_128[47:40]=data_reg_var[2]; \ + data_reg_128[39:32]=data_reg_var[7]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[1]; \ + data_reg_128[15:8]=data_reg_var[6]; \ + data_reg_128[7:0]=data_reg_var[11]; + +`define invert_shift_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[13]; \ + data_reg_128[111:104]=data_reg_var[10]; \ + data_reg_128[103:96]=data_reg_var[7]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[1]; \ + data_reg_128[79:72]=data_reg_var[14]; \ + data_reg_128[71:64]=data_reg_var[11]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[5]; \ + data_reg_128[47:40]=data_reg_var[2]; \ + data_reg_128[39:32]=data_reg_var[15]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[9]; \ + data_reg_128[15:8]=data_reg_var[6]; \ + data_reg_128[7:0]=data_reg_var[3]; + + +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) +begin + + data_reg = (0); + state = (0); + ready_o = (0); + +end +else +begin + + data_reg = (next_data_reg); + state = (next_state); + ready_o = (next_ready_o); + +end + + +end +//sub: +reg[127:0] data_i_var,data_reg_128; +reg[7:0] data_array[15:0],data_reg_var[15:0]; + +always @( decrypt_i or start_i or state or data_i or sbox_data_i or data_reg) + +begin + + + data_i_var=data_i; + + data_array[0]=data_i_var[127:120]; + data_array[1]=data_i_var[119:112]; + data_array[2]=data_i_var[111:104]; + data_array[3]=data_i_var[103:96]; + data_array[4]=data_i_var[95:88]; + data_array[5]=data_i_var[87:80]; + data_array[6]=data_i_var[79:72]; + data_array[7]=data_i_var[71:64]; + data_array[8]=data_i_var[63:56]; + data_array[9]=data_i_var[55:48]; + data_array[10]=data_i_var[47:40]; + data_array[11]=data_i_var[39:32]; + data_array[12]=data_i_var[31:24]; + data_array[13]=data_i_var[23:16]; + data_array[14]=data_i_var[15:8]; + data_array[15]=data_i_var[7:0]; + + data_reg_var[0]=data_reg[127:120]; + data_reg_var[1]=data_reg[119:112]; + data_reg_var[2]=data_reg[111:104]; + data_reg_var[3]=data_reg[103:96]; + data_reg_var[4]=data_reg[95:88]; + data_reg_var[5]=data_reg[87:80]; + data_reg_var[6]=data_reg[79:72]; + data_reg_var[7]=data_reg[71:64]; + data_reg_var[8]=data_reg[63:56]; + data_reg_var[9]=data_reg[55:48]; + data_reg_var[10]=data_reg[47:40]; + data_reg_var[11]=data_reg[39:32]; + data_reg_var[12]=data_reg[31:24]; + data_reg_var[13]=data_reg[23:16]; + data_reg_var[14]=data_reg[15:8]; + data_reg_var[15]=data_reg[7:0]; + + + sbox_decrypt_o = (decrypt_i); + sbox_data_o = (0); + next_state = (state); + next_data_reg = (data_reg); + + next_ready_o = (0); + data_o = (data_reg); + + case(state) + + 0: +begin + if(start_i) +begin + +sbox_data_o = (data_array[0]); + next_state = (1); + +end + + end + 16: +begin + data_reg_var[15]=sbox_data_i; + //Makeshiftrowsstage + case(decrypt_i) + 0: + begin + `shift_array_to_128 + end + 1: + begin + `invert_shift_array_to_128 + end + endcase + + next_data_reg = (data_reg_128); + next_ready_o = (1); + next_state = (0); + end + default: + begin + sbox_data_o = (data_array[state]); + data_reg_var[state-1]=sbox_data_i; + `assign_array_to_128 + next_data_reg = (data_reg_128); + next_state = (state+1); + end + +endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v new file mode 100644 index 000000000..ff9e265a8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v new file mode 100644 index 000000000..9308ccc9b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns for a 16 bit word module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum for a 16 bit word //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: word_mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module word_mixcolum(in,outx,outy); +input [31:0] in; +output [31:0] outx; +output [31:0] outy; + +reg [31:0] outx; +reg [31:0] outy; + +reg [7:0] a; +reg [7:0] b; +reg [7:0] c; +reg [7:0] d; +wire [7:0] x1; + +wire [7:0] x2; + +wire [7:0] x3; + +wire [7:0] x4; + +wire [7:0] y1; + +wire [7:0] y2; + +wire [7:0] y3; + +wire [7:0] y4; + + +byte_mixcolum bm1 (.a(a), .b(b), .c(c), .d(d), .outx(x1), .outy(y1)); +byte_mixcolum bm2 (.a(b), .b(c), .c(d), .d(a), .outx(x2), .outy(y2)); +byte_mixcolum bm3 (.a(c), .b(d), .c(a), .d(b), .outx(x3), .outy(y3)); +byte_mixcolum bm4 (.a(d), .b(a), .c(b), .d(c), .outx(x4), .outy(y4)); + + + reg[31:0] in_var; + reg[31:0] outx_var,outy_var; +//split: +always @( in) + +begin + + + + in_var=in; + a = (in_var[31:24]); + b = (in_var[23:16]); + c = (in_var[15:8]); + d = (in_var[7:0]); + +end +//mix: +always @( x1 or x2 or x3 or x4 or y1 or y2 or y3 or y4) + +begin + + + + outx_var[31:24]=x1; + outx_var[23:16]=x2; + outx_var[15:8]=x3; + outx_var[7:0]=x4; + outy_var[31:24]=y1; + outy_var[23:16]=y2; + outy_var[15:8]=y3; + outy_var[7:0]=y4; + + outx = (outx_var); + outy = (outy_var); + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/des.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/des.v new file mode 100644 index 000000000..3147cb01d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/des.v @@ -0,0 +1,284 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// DES Top //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Top file of DES project //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: des.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module des(clk,reset,load_i,decrypt_i,data_i,key_i,data_o,ready_o); +input clk; +input reset; +input load_i; +input decrypt_i; +input [63:0] data_i; +input [63:0] key_i; +output [63:0] data_o; +output ready_o; + +reg [63:0] data_o; +reg ready_o; + + +reg [3:0] stage1_iter; + +reg [3:0] next_stage1_iter; + +reg next_ready_o; + +reg[63:0] next_data_o; + +reg data_ready; + +reg next_data_ready; + +reg [31:0] stage1_L_i; + +reg [31:0] stage1_R_i; + +reg [55:0] stage1_round_key_i; + +reg [3:0] stage1_iteration_i; +wire [31:0] stage1_R_o; +wire [31:0] stage1_L_o; +wire [55:0] stage1_round_key_o; +wire [5:0] s1_stag1_i; +wire [5:0] s2_stag1_i; +wire [5:0] s3_stag1_i; +wire [5:0] s4_stag1_i; +wire [5:0] s5_stag1_i; +wire [5:0] s6_stag1_i; +wire [5:0] s7_stag1_i; +wire [5:0] s8_stag1_i; +wire [3:0] s1_stag1_o; +wire [3:0] s2_stag1_o; +wire [3:0] s3_stag1_o; +wire [3:0] s4_stag1_o; +wire [3:0] s5_stag1_o; +wire [3:0] s6_stag1_o; +wire [3:0] s7_stag1_o; +wire [3:0] s8_stag1_o; + +reg[31:0] L_i_var,R_i_var; +reg[63:0] data_i_var,data_o_var,data_o_var_t,key_i_var; +reg[55:0] key_var_perm; + + +desround rd1 (.clk(clk), .reset(reset), .iteration_i(stage1_iteration_i), .decrypt_i(decrypt_i), .R_i(stage1_R_i), .L_i(stage1_L_i), .Key_i(stage1_round_key_i), .R_o(stage1_R_o), .L_o(stage1_L_o), .Key_o(stage1_round_key_o), .s1_o(s1_stag1_i), .s2_o(s2_stag1_i), .s3_o(s3_stag1_i), .s4_o(s4_stag1_i), .s5_o(s5_stag1_i), .s6_o(s6_stag1_i), .s7_o(s7_stag1_i), .s8_o(s8_stag1_i), .s1_i(s1_stag1_o), .s2_i(s2_stag1_o), .s3_i(s3_stag1_o), .s4_i(s4_stag1_o), .s5_i(s5_stag1_o), .s6_i(s6_stag1_o), .s7_i(s7_stag1_o), .s8_i(s8_stag1_o)); +s1 sbox1 (.stage1_input(s1_stag1_i), .stage1_output(s1_stag1_o)); +s2 sbox2 (.stage1_input(s2_stag1_i), .stage1_output(s2_stag1_o)); +s3 sbox3 (.stage1_input(s3_stag1_i), .stage1_output(s3_stag1_o)); +s4 sbox4 (.stage1_input(s4_stag1_i), .stage1_output(s4_stag1_o)); +s5 sbox5 (.stage1_input(s5_stag1_i), .stage1_output(s5_stag1_o)); +s6 sbox6 (.stage1_input(s6_stag1_i), .stage1_output(s6_stag1_o)); +s7 sbox7 (.stage1_input(s7_stag1_i), .stage1_output(s7_stag1_o)); +s8 sbox8 (.stage1_input(s8_stag1_i), .stage1_output(s8_stag1_o)); + +always @(posedge clk or negedge reset) + +begin + + if(!reset) + begin + + ready_o = (0); + data_o = (0); + stage1_iter = (0); + data_ready = (1); + + end + else + begin + + ready_o = (next_ready_o); + data_o = (next_data_o); + stage1_iter = (next_stage1_iter); + data_ready = (next_data_ready); + + end +end + + +always @( data_i or key_i or load_i or stage1_iter or data_ready or stage1_R_o or stage1_L_o or stage1_round_key_o) + +begin + + + + L_i_var=0; + R_i_var=0; + data_i_var=0; + + next_ready_o = (0); + next_data_ready = (data_ready); + next_stage1_iter = (stage1_iter); + + stage1_L_i = (0); + stage1_R_i = (0); + stage1_round_key_i = (0); + + + key_i_var=key_i; + + key_var_perm[55]=key_i_var[7];key_var_perm[54]=key_i_var[15];key_var_perm[53]=key_i_var[23];key_var_perm[52]=key_i_var[31]; + key_var_perm[51]=key_i_var[39];key_var_perm[50]=key_i_var[47];key_var_perm[49]=key_i_var[55];key_var_perm[48]=key_i_var[63]; + + key_var_perm[47]=key_i_var[6];key_var_perm[46]=key_i_var[14];key_var_perm[45]=key_i_var[22];key_var_perm[44]=key_i_var[30]; + key_var_perm[43]=key_i_var[38];key_var_perm[42]=key_i_var[46];key_var_perm[41]=key_i_var[54];key_var_perm[40]=key_i_var[62]; + + key_var_perm[39]=key_i_var[5];key_var_perm[38]=key_i_var[13];key_var_perm[37]=key_i_var[21];key_var_perm[36]=key_i_var[29]; + key_var_perm[35]=key_i_var[37];key_var_perm[34]=key_i_var[45];key_var_perm[33]=key_i_var[53];key_var_perm[32]=key_i_var[61]; + + key_var_perm[31]=key_i_var[4];key_var_perm[30]=key_i_var[12];key_var_perm[29]=key_i_var[20];key_var_perm[28]=key_i_var[28]; + key_var_perm[27]=key_i_var[1];key_var_perm[26]=key_i_var[9];key_var_perm[25]=key_i_var[17];key_var_perm[24]=key_i_var[25]; + + key_var_perm[23]=key_i_var[33];key_var_perm[22]=key_i_var[41];key_var_perm[21]=key_i_var[49];key_var_perm[20]=key_i_var[57]; + key_var_perm[19]=key_i_var[2];key_var_perm[18]=key_i_var[10];key_var_perm[17]=key_i_var[18];key_var_perm[16]=key_i_var[26]; + + key_var_perm[15]=key_i_var[34];key_var_perm[14]=key_i_var[42];key_var_perm[13]=key_i_var[50];key_var_perm[12]=key_i_var[58]; + key_var_perm[11]=key_i_var[3];key_var_perm[10]=key_i_var[11];key_var_perm[9]=key_i_var[19];key_var_perm[8]=key_i_var[27]; + + key_var_perm[7]=key_i_var[35];key_var_perm[6]=key_i_var[43];key_var_perm[5]=key_i_var[51];key_var_perm[4]=key_i_var[59]; + key_var_perm[3]=key_i_var[36];key_var_perm[2]=key_i_var[44];key_var_perm[1]=key_i_var[52];key_var_perm[0]=key_i_var[60]; + + + data_i_var=data_i; + L_i_var[31]=data_i_var[6];L_i_var[30]=data_i_var[14];L_i_var[29]=data_i_var[22];L_i_var[28]=data_i_var[30]; + L_i_var[27]=data_i_var[38];L_i_var[26]=data_i_var[46];L_i_var[25]=data_i_var[54];L_i_var[24]=data_i_var[62]; + + L_i_var[23]=data_i_var[4];L_i_var[22]=data_i_var[12];L_i_var[21]=data_i_var[20];L_i_var[20]=data_i_var[28]; + L_i_var[19]=data_i_var[36];L_i_var[18]=data_i_var[44];L_i_var[17]=data_i_var[52];L_i_var[16]=data_i_var[60]; + + L_i_var[15]=data_i_var[2];L_i_var[14]=data_i_var[10];L_i_var[13]=data_i_var[18];L_i_var[12]=data_i_var[26]; + L_i_var[11]=data_i_var[34];L_i_var[10]=data_i_var[42];L_i_var[9]=data_i_var[50];L_i_var[8]=data_i_var[58]; + + L_i_var[7]=data_i_var[0];L_i_var[6]=data_i_var[8];L_i_var[5]=data_i_var[16];L_i_var[4]=data_i_var[24]; + L_i_var[3]=data_i_var[32];L_i_var[2]=data_i_var[40];L_i_var[1]=data_i_var[48];L_i_var[0]=data_i_var[56]; + + R_i_var[31]=data_i_var[7];R_i_var[30]=data_i_var[15];R_i_var[29]=data_i_var[23];R_i_var[28]=data_i_var[31]; + R_i_var[27]=data_i_var[39];R_i_var[26]=data_i_var[47];R_i_var[25]=data_i_var[55];R_i_var[24]=data_i_var[63]; + + R_i_var[23]=data_i_var[5];R_i_var[22]=data_i_var[13];R_i_var[21]=data_i_var[21];R_i_var[20]=data_i_var[29]; + R_i_var[19]=data_i_var[37];R_i_var[18]=data_i_var[45];R_i_var[17]=data_i_var[53];R_i_var[16]=data_i_var[61]; + + R_i_var[15]=data_i_var[3];R_i_var[14]=data_i_var[11];R_i_var[13]=data_i_var[19];R_i_var[12]=data_i_var[27]; + R_i_var[11]=data_i_var[35];R_i_var[10]=data_i_var[43];R_i_var[9]=data_i_var[51];R_i_var[8]=data_i_var[59]; + + R_i_var[7]=data_i_var[1];R_i_var[6]=data_i_var[9];R_i_var[5]=data_i_var[17];R_i_var[4]=data_i_var[25]; + R_i_var[3]=data_i_var[33];R_i_var[2]=data_i_var[41];R_i_var[1]=data_i_var[49];R_i_var[0]=data_i_var[57]; + + + + data_o_var_t[63:32]=stage1_R_o; + data_o_var_t[31:0]=stage1_L_o; + + data_o_var[63]=data_o_var_t[24];data_o_var[62]=data_o_var_t[56];data_o_var[61]=data_o_var_t[16];data_o_var[60]=data_o_var_t[48]; + data_o_var[59]=data_o_var_t[8];data_o_var[58]=data_o_var_t[40];data_o_var[57]=data_o_var_t[0];data_o_var[56]=data_o_var_t[32]; + + data_o_var[55]=data_o_var_t[25];data_o_var[54]=data_o_var_t[57];data_o_var[53]=data_o_var_t[17];data_o_var[52]=data_o_var_t[49]; + data_o_var[51]=data_o_var_t[9];data_o_var[50]=data_o_var_t[41];data_o_var[49]=data_o_var_t[1];data_o_var[48]=data_o_var_t[33]; + + data_o_var[47]=data_o_var_t[26];data_o_var[46]=data_o_var_t[58];data_o_var[45]=data_o_var_t[18];data_o_var[44]=data_o_var_t[50]; + data_o_var[43]=data_o_var_t[10];data_o_var[42]=data_o_var_t[42];data_o_var[41]=data_o_var_t[2];data_o_var[40]=data_o_var_t[34]; + + data_o_var[39]=data_o_var_t[27];data_o_var[38]=data_o_var_t[59];data_o_var[37]=data_o_var_t[19];data_o_var[36]=data_o_var_t[51]; + data_o_var[35]=data_o_var_t[11];data_o_var[34]=data_o_var_t[43];data_o_var[33]=data_o_var_t[3];data_o_var[32]=data_o_var_t[35]; + + data_o_var[31]=data_o_var_t[28];data_o_var[30]=data_o_var_t[60];data_o_var[29]=data_o_var_t[20];data_o_var[28]=data_o_var_t[52]; + data_o_var[27]=data_o_var_t[12];data_o_var[26]=data_o_var_t[44];data_o_var[25]=data_o_var_t[4];data_o_var[24]=data_o_var_t[36]; + + data_o_var[23]=data_o_var_t[29];data_o_var[22]=data_o_var_t[61];data_o_var[21]=data_o_var_t[21];data_o_var[20]=data_o_var_t[53]; + data_o_var[19]=data_o_var_t[13];data_o_var[18]=data_o_var_t[45];data_o_var[17]=data_o_var_t[5];data_o_var[16]=data_o_var_t[37]; + + data_o_var[15]=data_o_var_t[30];data_o_var[14]=data_o_var_t[62];data_o_var[13]=data_o_var_t[22];data_o_var[12]=data_o_var_t[54]; + data_o_var[11]=data_o_var_t[14];data_o_var[10]=data_o_var_t[46];data_o_var[9]=data_o_var_t[6];data_o_var[8]=data_o_var_t[38]; + + data_o_var[7]=data_o_var_t[31];data_o_var[6]=data_o_var_t[63];data_o_var[5]=data_o_var_t[23];data_o_var[4]=data_o_var_t[55]; + data_o_var[3]=data_o_var_t[15];data_o_var[2]=data_o_var_t[47];data_o_var[1]=data_o_var_t[7];data_o_var[0]=data_o_var_t[39]; + + next_data_o = (data_o_var); + + stage1_iteration_i = (stage1_iter); + + next_ready_o = (0); + stage1_L_i = (stage1_L_o); + stage1_R_i = (stage1_R_o); + stage1_round_key_i = (stage1_round_key_o); + + case(stage1_iter) + + 0: + begin + if(load_i) + begin + next_stage1_iter = (1); + stage1_L_i = (L_i_var); + stage1_R_i = (R_i_var); + stage1_round_key_i = (key_var_perm); + next_data_ready = (0); + end + else if (!data_ready) + begin + + next_stage1_iter = (0); + next_ready_o = (1); + next_data_ready = (1); + end + end + + 15: + next_stage1_iter = (0); + + default: + next_stage1_iter = (stage1_iter+1); + +endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v new file mode 100644 index 000000000..bc817b5b3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v @@ -0,0 +1,223 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// DES Round //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Performs a round of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: desround.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:16 jcastillo +// First import +// + + +module desround(clk,reset,iteration_i,decrypt_i,R_i,L_i,Key_i,R_o,L_o,Key_o,s1_o,s2_o,s3_o,s4_o,s5_o,s6_o,s7_o,s8_o,s1_i,s2_i,s3_i,s4_i,s5_i,s6_i,s7_i,s8_i); + +input clk; +input reset; +input [3:0] iteration_i; +input decrypt_i; +input [31:0] R_i; +input [31:0] L_i; +input [55:0] Key_i; +output [31:0] R_o; +output [31:0] L_o; +output [55:0] Key_o; +output [5:0] s1_o; +output [5:0] s2_o; +output [5:0] s3_o; +output [5:0] s4_o; +output [5:0] s5_o; +output [5:0] s6_o; +output [5:0] s7_o; +output [5:0] s8_o; +input [3:0] s1_i; +input [3:0] s2_i; +input [3:0] s3_i; +input [3:0] s4_i; +input [3:0] s5_i; +input [3:0] s6_i; +input [3:0] s7_i; +input [3:0] s8_i; + +reg [31:0] R_o; +reg [31:0] L_o; +reg [55:0] Key_o; +reg [5:0] s1_o; +reg [5:0] s2_o; +reg [5:0] s3_o; +reg [5:0] s4_o; +reg [5:0] s5_o; +reg [5:0] s6_o; +reg [5:0] s7_o; +reg [5:0] s8_o; + + + +reg [55:0] previous_key; + +reg [3:0] iteration; + +reg decrypt; + + + +wire [55:0] non_perm_key; + + + +wire [47:0] new_key; + +reg [31:0] next_R; + +reg [31:0] expanRSig; + + reg[47:0] expandedR; + reg[47:0] round_key; + reg[47:0] KER; + reg[31:0] R_i_var; + + reg[31:0] Soutput; + reg[31:0] f; + + +key_gen kg1 (.previous_key(previous_key), .iteration(iteration), .decrypt(decrypt), .new_key(new_key), .non_perm_key(non_perm_key)); + +always @(posedge clk or negedge reset) + +begin + + + if(!reset) + begin + + L_o = (0); + R_o = (0); + Key_o = (0); + + end + else + begin + + L_o = (R_i); + R_o = (next_R); + Key_o = (non_perm_key); + + end + +end + +always @( R_i or L_i or Key_i or iteration_i or decrypt_i or new_key or s1_i or s2_i or s3_i or s4_i or s5_i or s6_i or s7_i or s8_i) + +begin + + R_i_var=R_i; + + + expandedR[47]=R_i_var[0]; expandedR[46]=R_i_var[31]; expandedR[45]=R_i_var[30]; expandedR[44]=R_i_var[29]; + expandedR[43]=R_i_var[28]; expandedR[42]=R_i_var[27]; expandedR[41]=R_i_var[28]; expandedR[40]=R_i_var[27]; + + expandedR[39]=R_i_var[26]; expandedR[38]=R_i_var[25]; expandedR[37]=R_i_var[24]; expandedR[36]=R_i_var[23]; + expandedR[35]=R_i_var[24]; expandedR[34]=R_i_var[23]; expandedR[33]=R_i_var[22]; expandedR[32]=R_i_var[21]; + + expandedR[31]=R_i_var[20]; expandedR[30]=R_i_var[19]; expandedR[29]=R_i_var[20]; expandedR[28]=R_i_var[19]; + expandedR[27]=R_i_var[18]; expandedR[26]=R_i_var[17]; expandedR[25]=R_i_var[16]; expandedR[24]=R_i_var[15]; + + expandedR[23]=R_i_var[16]; expandedR[22]=R_i_var[15]; expandedR[21]=R_i_var[14]; expandedR[20]=R_i_var[13]; + expandedR[19]=R_i_var[12]; expandedR[18]=R_i_var[11]; expandedR[17]=R_i_var[12]; expandedR[16]=R_i_var[11]; + + expandedR[15]=R_i_var[10]; expandedR[14]=R_i_var[9]; expandedR[13]=R_i_var[8]; expandedR[12]=R_i_var[7]; + expandedR[11]=R_i_var[8]; expandedR[10]=R_i_var[7]; expandedR[9]=R_i_var[6]; expandedR[8]=R_i_var[5]; + + expandedR[7]=R_i_var[4]; expandedR[6]=R_i_var[3]; expandedR[5]=R_i_var[4]; expandedR[4]=R_i_var[3]; + expandedR[3]=R_i_var[2]; expandedR[2]=R_i_var[1]; expandedR[1]=R_i_var[0]; expandedR[0]=R_i_var[31]; + + + previous_key = (Key_i); + iteration = (iteration_i); + decrypt = (decrypt_i); + + round_key=new_key; + + KER=expandedR^round_key; + + + s1_o = (KER[47:42]); + s2_o = (KER[41:36]); + s3_o = (KER[35:30]); + s4_o = (KER[29:24]); + s5_o = (KER[23:18]); + s6_o = (KER[17:12]); + s7_o = (KER[11:6]); + s8_o = (KER[5:0]); + + Soutput[31:28]=s1_i; + Soutput[27:24]=s2_i; + Soutput[23:20]=s3_i; + Soutput[19:16]=s4_i; + Soutput[15:12]=s5_i; + Soutput[11:8]=s6_i; + Soutput[7:4]=s7_i; + Soutput[3:0]=s8_i; + + + + f[31]=Soutput[16]; f[30]=Soutput[25]; f[29]=Soutput[12]; f[28]=Soutput[11]; + f[27]=Soutput[3]; f[26]=Soutput[20]; f[25]=Soutput[4]; f[24]=Soutput[15]; + + f[23]=Soutput[31]; f[22]=Soutput[17]; f[21]=Soutput[9]; f[20]=Soutput[6]; + f[19]=Soutput[27]; f[18]=Soutput[14]; f[17]=Soutput[1]; f[16]=Soutput[22]; + + f[15]=Soutput[30]; f[14]=Soutput[24]; f[13]=Soutput[8]; f[12]=Soutput[18]; + f[11]=Soutput[0]; f[10]=Soutput[5]; f[9]=Soutput[29]; f[8]=Soutput[23]; + + f[7]=Soutput[13]; f[6]=Soutput[19]; f[5]=Soutput[2]; f[4]=Soutput[26]; + f[3]=Soutput[10]; f[2]=Soutput[21]; f[1]=Soutput[28]; f[0]=Soutput[7]; + + next_R = (L_i^f); + + expanRSig = (L_i^f); + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v new file mode 100644 index 000000000..523df364a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v @@ -0,0 +1,192 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Key generator //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Generate the next key from the previous one //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: key_gen.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module key_gen(previous_key,iteration,decrypt,non_perm_key,new_key); + +input [55:0] previous_key; +input [3:0] iteration; +input decrypt; +output [55:0] non_perm_key; +output [47:0] new_key; + +reg [55:0] non_perm_key; +reg [47:0] new_key; + + +reg prev0,prev1; +reg[55:0] prev_key_var,non_perm_key_var; +reg[47:0] new_key_var; +reg[27:0] semi_key; + + +always @( previous_key or iteration or decrypt) + +begin + + + + prev_key_var=previous_key; + new_key_var=0; + new_key = (0); + non_perm_key_var=0; + non_perm_key = (0); + + if(!decrypt) + begin + case(iteration) + + 0, 1, 8, 15: + begin + semi_key=prev_key_var[55:28]; + prev0=semi_key[27]; + semi_key=semi_key<<1; + semi_key[0]=prev0; + non_perm_key_var[55:28]=semi_key; + semi_key=prev_key_var[27:0]; + prev0=semi_key[27]; + semi_key=semi_key<<1; + semi_key[0]=prev0; + non_perm_key_var[27:0]=semi_key; + end + default: + begin + semi_key=prev_key_var[55:28]; + prev0=semi_key[27]; + prev1=semi_key[26]; + semi_key=semi_key<<2; + semi_key[1]=prev0; + semi_key[0]=prev1; + non_perm_key_var[55:28]=semi_key; + semi_key=prev_key_var[27:0]; + prev0=semi_key[27]; + prev1=semi_key[26]; + semi_key=semi_key<<2; + semi_key[1]=prev0; + semi_key[0]=prev1; + non_perm_key_var[27:0]=semi_key; + end + + endcase + end + else + begin + case(iteration) + + 0: + begin + semi_key=prev_key_var[55:28]; + non_perm_key_var[55:28]=semi_key; + semi_key=prev_key_var[27:0]; + non_perm_key_var[27:0]=semi_key; + end + 1, 8, 15: + begin + semi_key=prev_key_var[55:28]; + prev0=semi_key[0]; + semi_key=semi_key>>1; + semi_key[27]=prev0; + non_perm_key_var[55:28]=semi_key; + semi_key=prev_key_var[27:0]; + prev0=semi_key[0]; + semi_key=semi_key>>1; + semi_key[27]=prev0; + non_perm_key_var[27:0]=semi_key; + end + default: + begin + semi_key=prev_key_var[55:28]; + prev0=semi_key[0]; + prev1=semi_key[1]; + semi_key=semi_key>>2; + semi_key[26]=prev0; + semi_key[27]=prev1; + non_perm_key_var[55:28]=semi_key; + semi_key=prev_key_var[27:0]; + prev0=semi_key[0]; + prev1=semi_key[1]; + semi_key=semi_key>>2; + semi_key[26]=prev0; + semi_key[27]=prev1; + non_perm_key_var[27:0]=semi_key; + end + + endcase + end + + + non_perm_key = (non_perm_key_var); + + + new_key_var[47]=non_perm_key_var[42]; new_key_var[46]=non_perm_key_var[39]; new_key_var[45]=non_perm_key_var[45]; new_key_var[44]=non_perm_key_var[32]; + new_key_var[43]=non_perm_key_var[55]; new_key_var[42]=non_perm_key_var[51]; new_key_var[41]=non_perm_key_var[53]; new_key_var[40]=non_perm_key_var[28]; + + new_key_var[39]=non_perm_key_var[41]; new_key_var[38]=non_perm_key_var[50]; new_key_var[37]=non_perm_key_var[35]; new_key_var[36]=non_perm_key_var[46]; + new_key_var[35]=non_perm_key_var[33]; new_key_var[34]=non_perm_key_var[37]; new_key_var[33]=non_perm_key_var[44]; new_key_var[32]=non_perm_key_var[52]; + + new_key_var[31]=non_perm_key_var[30]; new_key_var[30]=non_perm_key_var[48]; new_key_var[29]=non_perm_key_var[40]; new_key_var[28]=non_perm_key_var[49]; + new_key_var[27]=non_perm_key_var[29]; new_key_var[26]=non_perm_key_var[36]; new_key_var[25]=non_perm_key_var[43]; new_key_var[24]=non_perm_key_var[54]; + + new_key_var[23]=non_perm_key_var[15]; new_key_var[22]=non_perm_key_var[4]; new_key_var[21]=non_perm_key_var[25]; new_key_var[20]=non_perm_key_var[19]; + new_key_var[19]=non_perm_key_var[9]; new_key_var[18]=non_perm_key_var[1]; new_key_var[17]=non_perm_key_var[26]; new_key_var[16]=non_perm_key_var[16]; + + new_key_var[15]=non_perm_key_var[5]; new_key_var[14]=non_perm_key_var[11]; new_key_var[13]=non_perm_key_var[23]; new_key_var[12]=non_perm_key_var[8]; + new_key_var[11]=non_perm_key_var[12]; new_key_var[10]=non_perm_key_var[7]; new_key_var[9]=non_perm_key_var[17]; new_key_var[8]=non_perm_key_var[0]; + + new_key_var[7]=non_perm_key_var[22]; new_key_var[6]=non_perm_key_var[3]; new_key_var[5]=non_perm_key_var[10]; new_key_var[4]=non_perm_key_var[14]; + new_key_var[3]=non_perm_key_var[6]; new_key_var[2]=non_perm_key_var[20]; new_key_var[1]=non_perm_key_var[27]; new_key_var[0]=non_perm_key_var[24]; + + new_key = (new_key_var); + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v new file mode 100644 index 000000000..a45f2e72a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v @@ -0,0 +1,137 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 1 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s1.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s1(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + + case(stage1_input) + 0: stage1_output = (14); + 1: stage1_output = (0); + 2: stage1_output = (4); + 3: stage1_output = (15); + 4: stage1_output = (13); + 5: stage1_output = (7); + 6: stage1_output = (1); + 7: stage1_output = (4); + 8: stage1_output = (2); + 9: stage1_output = (14); + 10: stage1_output = (15); + 11: stage1_output = (2); + 12: stage1_output = (11); + 13: stage1_output = (13); + 14: stage1_output = (8); + 15: stage1_output = (1); + 16: stage1_output = (3); + 17: stage1_output = (10); + 18: stage1_output = (10); + 19: stage1_output = (6); + 20: stage1_output = (6); + 21: stage1_output = (12); + 22: stage1_output = (12); + 23: stage1_output = (11); + 24: stage1_output = (5); + 25: stage1_output = (9); + 26: stage1_output = (9); + 27: stage1_output = (5); + 28: stage1_output = (0); + 29: stage1_output = (3); + 30: stage1_output = (7); + 31: stage1_output = (8); + 32: stage1_output = (4); + 33: stage1_output = (15); + 34: stage1_output = (1); + 35: stage1_output = (12); + 36: stage1_output = (14); + 37: stage1_output = (8); + 38: stage1_output = (8); + 39: stage1_output = (2); + 40: stage1_output = (13); + 41: stage1_output = (4); + 42: stage1_output = (6); + 43: stage1_output = (9); + 44: stage1_output = (2); + 45: stage1_output = (1); + 46: stage1_output = (11); + 47: stage1_output = (7); + 48: stage1_output = (15); + 49: stage1_output = (5); + 50: stage1_output = (12); + 51: stage1_output = (11); + 52: stage1_output = (9); + 53: stage1_output = (3); + 54: stage1_output = (7); + 55: stage1_output = (14); + 56: stage1_output = (3); + 57: stage1_output = (10); + 58: stage1_output = (10); + 59: stage1_output = (0); + 60: stage1_output = (5); + 61: stage1_output = (6); + 62: stage1_output = (0); + 63: stage1_output = (13); + +endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v new file mode 100644 index 000000000..4325020b5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v @@ -0,0 +1,137 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 2 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s2.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s2(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + + case(stage1_input) + 0: stage1_output = (15); + 1: stage1_output = (3); + 2: stage1_output = (1); + 3: stage1_output = (13); + 4: stage1_output = (8); + 5: stage1_output = (4); + 6: stage1_output = (14); + 7: stage1_output = (7); + 8: stage1_output = (6); + 9: stage1_output = (15); + 10: stage1_output = (11); + 11: stage1_output = (2); + 12: stage1_output = (3); + 13: stage1_output = (8); + 14: stage1_output = (4); + 15: stage1_output = (14); + 16: stage1_output = (9); + 17: stage1_output = (12); + 18: stage1_output = (7); + 19: stage1_output = (0); + 20: stage1_output = (2); + 21: stage1_output = (1); + 22: stage1_output = (13); + 23: stage1_output = (10); + 24: stage1_output = (12); + 25: stage1_output = (6); + 26: stage1_output = (0); + 27: stage1_output = (9); + 28: stage1_output = (5); + 29: stage1_output = (11); + 30: stage1_output = (10); + 31: stage1_output = (5); + 32: stage1_output = (0); + 33: stage1_output = (13); + 34: stage1_output = (14); + 35: stage1_output = (8); + 36: stage1_output = (7); + 37: stage1_output = (10); + 38: stage1_output = (11); + 39: stage1_output = (1); + 40: stage1_output = (10); + 41: stage1_output = (3); + 42: stage1_output = (4); + 43: stage1_output = (15); + 44: stage1_output = (13); + 45: stage1_output = (4); + 46: stage1_output = (1); + 47: stage1_output = (2); + 48: stage1_output = (5); + 49: stage1_output = (11); + 50: stage1_output = (8); + 51: stage1_output = (6); + 52: stage1_output = (12); + 53: stage1_output = (7); + 54: stage1_output = (6); + 55: stage1_output = (12); + 56: stage1_output = (9); + 57: stage1_output = (0); + 58: stage1_output = (3); + 59: stage1_output = (5); + 60: stage1_output = (2); + 61: stage1_output = (14); + 62: stage1_output = (15); + 63: stage1_output = (9); + +endcase + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v new file mode 100644 index 000000000..bc788205e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v @@ -0,0 +1,138 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 3 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s3.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s3(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (10); + 1: stage1_output = (13); + 2: stage1_output = (0); + 3: stage1_output = (7); + 4: stage1_output = (9); + 5: stage1_output = (0); + 6: stage1_output = (14); + 7: stage1_output = (9); + 8: stage1_output = (6); + 9: stage1_output = (3); + 10: stage1_output = (3); + 11: stage1_output = (4); + 12: stage1_output = (15); + 13: stage1_output = (6); + 14: stage1_output = (5); + 15: stage1_output = (10); + 16: stage1_output = (1); + 17: stage1_output = (2); + 18: stage1_output = (13); + 19: stage1_output = (8); + 20: stage1_output = (12); + 21: stage1_output = (5); + 22: stage1_output = (7); + 23: stage1_output = (14); + 24: stage1_output = (11); + 25: stage1_output = (12); + 26: stage1_output = (4); + 27: stage1_output = (11); + 28: stage1_output = (2); + 29: stage1_output = (15); + 30: stage1_output = (8); + 31: stage1_output = (1); + 32: stage1_output = (13); + 33: stage1_output = (1); + 34: stage1_output = (6); + 35: stage1_output = (10); + 36: stage1_output = (4); + 37: stage1_output = (13); + 38: stage1_output = (9); + 39: stage1_output = (0); + 40: stage1_output = (8); + 41: stage1_output = (6); + 42: stage1_output = (15); + 43: stage1_output = (9); + 44: stage1_output = (3); + 45: stage1_output = (8); + 46: stage1_output = (0); + 47: stage1_output = (7); + 48: stage1_output = (11); + 49: stage1_output = (4); + 50: stage1_output = (1); + 51: stage1_output = (15); + 52: stage1_output = (2); + 53: stage1_output = (14); + 54: stage1_output = (12); + 55: stage1_output = (3); + 56: stage1_output = (5); + 57: stage1_output = (11); + 58: stage1_output = (10); + 59: stage1_output = (5); + 60: stage1_output = (14); + 61: stage1_output = (2); + 62: stage1_output = (7); + 63: stage1_output = (12); + +endcase + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v new file mode 100644 index 000000000..3d3f29e46 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v @@ -0,0 +1,138 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 4 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s4.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s4(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (7); + 1: stage1_output = (13); + 2: stage1_output = (13); + 3: stage1_output = (8); + 4: stage1_output = (14); + 5: stage1_output = (11); + 6: stage1_output = (3); + 7: stage1_output = (5); + 8: stage1_output = (0); + 9: stage1_output = (6); + 10: stage1_output = (6); + 11: stage1_output = (15); + 12: stage1_output = (9); + 13: stage1_output = (0); + 14: stage1_output = (10); + 15: stage1_output = (3); + 16: stage1_output = (1); + 17: stage1_output = (4); + 18: stage1_output = (2); + 19: stage1_output = (7); + 20: stage1_output = (8); + 21: stage1_output = (2); + 22: stage1_output = (5); + 23: stage1_output = (12); + 24: stage1_output = (11); + 25: stage1_output = (1); + 26: stage1_output = (12); + 27: stage1_output = (10); + 28: stage1_output = (4); + 29: stage1_output = (14); + 30: stage1_output = (15); + 31: stage1_output = (9); + 32: stage1_output = (10); + 33: stage1_output = (3); + 34: stage1_output = (6); + 35: stage1_output = (15); + 36: stage1_output = (9); + 37: stage1_output = (0); + 38: stage1_output = (0); + 39: stage1_output = (6); + 40: stage1_output = (12); + 41: stage1_output = (10); + 42: stage1_output = (11); + 43: stage1_output = (1); + 44: stage1_output = (7); + 45: stage1_output = (13); + 46: stage1_output = (13); + 47: stage1_output = (8); + 48: stage1_output = (15); + 49: stage1_output = (9); + 50: stage1_output = (1); + 51: stage1_output = (4); + 52: stage1_output = (3); + 53: stage1_output = (5); + 54: stage1_output = (14); + 55: stage1_output = (11); + 56: stage1_output = (5); + 57: stage1_output = (12); + 58: stage1_output = (2); + 59: stage1_output = (7); + 60: stage1_output = (8); + 61: stage1_output = (2); + 62: stage1_output = (4); + 63: stage1_output = (14); + +endcase + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v new file mode 100644 index 000000000..30b679535 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v @@ -0,0 +1,139 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 5 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s5.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s5(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (2); + 1: stage1_output = (14); + 2: stage1_output = (12); + 3: stage1_output = (11); + 4: stage1_output = (4); + 5: stage1_output = (2); + 6: stage1_output = (1); + 7: stage1_output = (12); + 8: stage1_output = (7); + 9: stage1_output = (4); + 10: stage1_output = (10); + 11: stage1_output = (7); + 12: stage1_output = (11); + 13: stage1_output = (13); + 14: stage1_output = (6); + 15: stage1_output = (1); + 16: stage1_output = (8); + 17: stage1_output = (5); + 18: stage1_output = (5); + 19: stage1_output = (0); + 20: stage1_output = (3); + 21: stage1_output = (15); + 22: stage1_output = (15); + 23: stage1_output = (10); + 24: stage1_output = (13); + 25: stage1_output = (3); + 26: stage1_output = (0); + 27: stage1_output = (9); + 28: stage1_output = (14); + 29: stage1_output = (8); + 30: stage1_output = (9); + 31: stage1_output = (6); + 32: stage1_output = (4); + 33: stage1_output = (11); + 34: stage1_output = (2); + 35: stage1_output = (8); + 36: stage1_output = (1); + 37: stage1_output = (12); + 38: stage1_output = (11); + 39: stage1_output = (7); + 40: stage1_output = (10); + 41: stage1_output = (1); + 42: stage1_output = (13); + 43: stage1_output = (14); + 44: stage1_output = (7); + 45: stage1_output = (2); + 46: stage1_output = (8); + 47: stage1_output = (13); + 48: stage1_output = (15); + 49: stage1_output = (6); + 50: stage1_output = (9); + 51: stage1_output = (15); + 52: stage1_output = (12); + 53: stage1_output = (0); + 54: stage1_output = (5); + 55: stage1_output = (9); + 56: stage1_output = (6); + 57: stage1_output = (10); + 58: stage1_output = (3); + 59: stage1_output = (4); + 60: stage1_output = (0); + 61: stage1_output = (5); + 62: stage1_output = (14); + 63: stage1_output = (3); + +endcase + + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v new file mode 100644 index 000000000..bc6be866c --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v @@ -0,0 +1,139 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 6 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s6.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + + +module s6(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (12); + 1: stage1_output = (10); + 2: stage1_output = (1); + 3: stage1_output = (15); + 4: stage1_output = (10); + 5: stage1_output = (4); + 6: stage1_output = (15); + 7: stage1_output = (2); + 8: stage1_output = (9); + 9: stage1_output = (7); + 10: stage1_output = (2); + 11: stage1_output = (12); + 12: stage1_output = (6); + 13: stage1_output = (9); + 14: stage1_output = (8); + 15: stage1_output = (5); + 16: stage1_output = (0); + 17: stage1_output = (6); + 18: stage1_output = (13); + 19: stage1_output = (1); + 20: stage1_output = (3); + 21: stage1_output = (13); + 22: stage1_output = (4); + 23: stage1_output = (14); + 24: stage1_output = (14); + 25: stage1_output = (0); + 26: stage1_output = (7); + 27: stage1_output = (11); + 28: stage1_output = (5); + 29: stage1_output = (3); + 30: stage1_output = (11); + 31: stage1_output = (8); + 32: stage1_output = (9); + 33: stage1_output = (4); + 34: stage1_output = (14); + 35: stage1_output = (3); + 36: stage1_output = (15); + 37: stage1_output = (2); + 38: stage1_output = (5); + 39: stage1_output = (12); + 40: stage1_output = (2); + 41: stage1_output = (9); + 42: stage1_output = (8); + 43: stage1_output = (5); + 44: stage1_output = (12); + 45: stage1_output = (15); + 46: stage1_output = (3); + 47: stage1_output = (10); + 48: stage1_output = (7); + 49: stage1_output = (11); + 50: stage1_output = (0); + 51: stage1_output = (14); + 52: stage1_output = (4); + 53: stage1_output = (1); + 54: stage1_output = (10); + 55: stage1_output = (7); + 56: stage1_output = (1); + 57: stage1_output = (6); + 58: stage1_output = (13); + 59: stage1_output = (0); + 60: stage1_output = (11); + 61: stage1_output = (8); + 62: stage1_output = (6); + 63: stage1_output = (13); + +endcase + + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v new file mode 100644 index 000000000..323c911cf --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v @@ -0,0 +1,138 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 7 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s7.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + +module s7(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @( stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (4); + 1: stage1_output = (13); + 2: stage1_output = (11); + 3: stage1_output = (0); + 4: stage1_output = (2); + 5: stage1_output = (11); + 6: stage1_output = (14); + 7: stage1_output = (7); + 8: stage1_output = (15); + 9: stage1_output = (4); + 10: stage1_output = (0); + 11: stage1_output = (9); + 12: stage1_output = (8); + 13: stage1_output = (1); + 14: stage1_output = (13); + 15: stage1_output = (10); + 16: stage1_output = (3); + 17: stage1_output = (14); + 18: stage1_output = (12); + 19: stage1_output = (3); + 20: stage1_output = (9); + 21: stage1_output = (5); + 22: stage1_output = (7); + 23: stage1_output = (12); + 24: stage1_output = (5); + 25: stage1_output = (2); + 26: stage1_output = (10); + 27: stage1_output = (15); + 28: stage1_output = (6); + 29: stage1_output = (8); + 30: stage1_output = (1); + 31: stage1_output = (6); + 32: stage1_output = (1); + 33: stage1_output = (6); + 34: stage1_output = (4); + 35: stage1_output = (11); + 36: stage1_output = (11); + 37: stage1_output = (13); + 38: stage1_output = (13); + 39: stage1_output = (8); + 40: stage1_output = (12); + 41: stage1_output = (1); + 42: stage1_output = (3); + 43: stage1_output = (4); + 44: stage1_output = (7); + 45: stage1_output = (10); + 46: stage1_output = (14); + 47: stage1_output = (7); + 48: stage1_output = (10); + 49: stage1_output = (9); + 50: stage1_output = (15); + 51: stage1_output = (5); + 52: stage1_output = (6); + 53: stage1_output = (0); + 54: stage1_output = (8); + 55: stage1_output = (15); + 56: stage1_output = (0); + 57: stage1_output = (14); + 58: stage1_output = (5); + 59: stage1_output = (2); + 60: stage1_output = (9); + 61: stage1_output = (3); + 62: stage1_output = (2); + 63: stage1_output = (12); + +endcase + + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v new file mode 100644 index 000000000..a3e2ec469 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v @@ -0,0 +1,137 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// SBOX 8 //// +//// //// +//// This file is part of the SystemC DES //// +//// //// +//// Description: //// +//// Sbox of DES algorithm //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: s8.v,v $ +// Revision 1.1.1.1 2004/07/05 17:31:17 jcastillo +// First import +// + +module s8(stage1_input,stage1_output); +input [5:0] stage1_input; +output [3:0] stage1_output; + +reg [3:0] stage1_output; + + + +always @(stage1_input) + +begin + + case(stage1_input) + + 0: stage1_output = (13); + 1: stage1_output = (1); + 2: stage1_output = (2); + 3: stage1_output = (15); + 4: stage1_output = (8); + 5: stage1_output = (13); + 6: stage1_output = (4); + 7: stage1_output = (8); + 8: stage1_output = (6); + 9: stage1_output = (10); + 10: stage1_output = (15); + 11: stage1_output = (3); + 12: stage1_output = (11); + 13: stage1_output = (7); + 14: stage1_output = (1); + 15: stage1_output = (4); + 16: stage1_output = (10); + 17: stage1_output = (12); + 18: stage1_output = (9); + 19: stage1_output = (5); + 20: stage1_output = (3); + 21: stage1_output = (6); + 22: stage1_output = (14); + 23: stage1_output = (11); + 24: stage1_output = (5); + 25: stage1_output = (0); + 26: stage1_output = (0); + 27: stage1_output = (14); + 28: stage1_output = (12); + 29: stage1_output = (9); + 30: stage1_output = (7); + 31: stage1_output = (2); + 32: stage1_output = (7); + 33: stage1_output = (2); + 34: stage1_output = (11); + 35: stage1_output = (1); + 36: stage1_output = (4); + 37: stage1_output = (14); + 38: stage1_output = (1); + 39: stage1_output = (7); + 40: stage1_output = (9); + 41: stage1_output = (4); + 42: stage1_output = (12); + 43: stage1_output = (10); + 44: stage1_output = (14); + 45: stage1_output = (8); + 46: stage1_output = (2); + 47: stage1_output = (13); + 48: stage1_output = (0); + 49: stage1_output = (15); + 50: stage1_output = (6); + 51: stage1_output = (12); + 52: stage1_output = (10); + 53: stage1_output = (9); + 54: stage1_output = (13); + 55: stage1_output = (0); + 56: stage1_output = (15); + 57: stage1_output = (3); + 58: stage1_output = (3); + 59: stage1_output = (5); + 60: stage1_output = (5); + 61: stage1_output = (6); + 62: stage1_output = (8); + 63: stage1_output = (11); + +endcase + + + +end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v new file mode 100644 index 000000000..2f015e219 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v @@ -0,0 +1,442 @@ +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80_alu (/*AUTOARG*/ + // Outputs + Q, F_Out, + // Inputs + Arith16, Z16, ALU_Op, IR, ISet, BusA, BusB, F_In + ); + + parameter Mode = 0; + parameter Flag_C = 0; + parameter Flag_N = 1; + parameter Flag_P = 2; + parameter Flag_X = 3; + parameter Flag_H = 4; + parameter Flag_Y = 5; + parameter Flag_Z = 6; + parameter Flag_S = 7; + + input Arith16; + input Z16; + input [3:0] ALU_Op ; + input [5:0] IR; + input [1:0] ISet; + input [7:0] BusA; + input [7:0] BusB; + input [7:0] F_In; + output [7:0] Q; + output [7:0] F_Out; + reg [7:0] Q; + reg [7:0] F_Out; + + function [4:0] AddSub4; + input [3:0] A; + input [3:0] B; + input Sub; + input Carry_In; + begin + AddSub4 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; + end + endfunction // AddSub4 + + function [3:0] AddSub3; + input [2:0] A; + input [2:0] B; + input Sub; + input Carry_In; + begin + AddSub3 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; + end + endfunction // AddSub4 + + function [1:0] AddSub1; + input A; + input B; + input Sub; + input Carry_In; + begin + AddSub1 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; + end + endfunction // AddSub4 + + // AddSub variables (temporary signals) + reg UseCarry; + reg Carry7_v; + reg OverFlow_v; + reg HalfCarry_v; + reg Carry_v; + reg [7:0] Q_v; + + reg [7:0] BitMask; + + + always @(/*AUTOSENSE*/ALU_Op or BusA or BusB or F_In or IR) + begin + case (IR[5:3]) + 3'b000 : BitMask = 8'b00000001; + 3'b001 : BitMask = 8'b00000010; + 3'b010 : BitMask = 8'b00000100; + 3'b011 : BitMask = 8'b00001000; + 3'b100 : BitMask = 8'b00010000; + 3'b101 : BitMask = 8'b00100000; + 3'b110 : BitMask = 8'b01000000; + default: BitMask = 8'b10000000; + endcase // case(IR[5:3]) + + UseCarry = ~ ALU_Op[2] && ALU_Op[0]; + { HalfCarry_v, Q_v[3:0] } = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1], ALU_Op[1] ^ (UseCarry && F_In[Flag_C]) ); + { Carry7_v, Q_v[6:4] } = AddSub3(BusA[6:4], BusB[6:4], ALU_Op[1], HalfCarry_v); + { Carry_v, Q_v[7] } = AddSub1(BusA[7], BusB[7], ALU_Op[1], Carry7_v); + OverFlow_v = Carry_v ^ Carry7_v; + end // always @ * + + reg [7:0] Q_t; + reg [8:0] DAA_Q; + + always @ (/*AUTOSENSE*/ALU_Op or Arith16 or BitMask or BusA or BusB + or Carry_v or F_In or HalfCarry_v or IR or ISet + or OverFlow_v or Q_v or Z16) + begin + Q_t = 8'hxx; + DAA_Q = {9{1'bx}}; + + F_Out = F_In; + case (ALU_Op) + 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 : + begin + F_Out[Flag_N] = 1'b0; + F_Out[Flag_C] = 1'b0; + + case (ALU_Op[2:0]) + + 3'b000, 3'b001 : // ADD, ADC + begin + Q_t = Q_v; + F_Out[Flag_C] = Carry_v; + F_Out[Flag_H] = HalfCarry_v; + F_Out[Flag_P] = OverFlow_v; + end + + 3'b010, 3'b011, 3'b111 : // SUB, SBC, CP + begin + Q_t = Q_v; + F_Out[Flag_N] = 1'b1; + F_Out[Flag_C] = ~ Carry_v; + F_Out[Flag_H] = ~ HalfCarry_v; + F_Out[Flag_P] = OverFlow_v; + end + + 3'b100 : // AND + begin + Q_t[7:0] = BusA & BusB; + F_Out[Flag_H] = 1'b1; + end + + 3'b101 : // XOR + begin + Q_t[7:0] = BusA ^ BusB; + F_Out[Flag_H] = 1'b0; + end + + default : // OR 3'b110 + begin + Q_t[7:0] = BusA | BusB; + F_Out[Flag_H] = 1'b0; + end + + endcase // case(ALU_OP[2:0]) + + if (ALU_Op[2:0] == 3'b111 ) + begin // CP + F_Out[Flag_X] = BusB[3]; + F_Out[Flag_Y] = BusB[5]; + end + else + begin + F_Out[Flag_X] = Q_t[3]; + F_Out[Flag_Y] = Q_t[5]; + end + + if (Q_t[7:0] == 8'b00000000 ) + begin + F_Out[Flag_Z] = 1'b1; + if (Z16 == 1'b1 ) + begin + F_Out[Flag_Z] = F_In[Flag_Z]; // 16 bit ADC,SBC + end + end + else + begin + F_Out[Flag_Z] = 1'b0; + end // else: !if(Q_t[7:0] == 8'b00000000 ) + + F_Out[Flag_S] = Q_t[7]; + case (ALU_Op[2:0]) + 3'b000, 3'b001, 3'b010, 3'b011, 3'b111 : // ADD, ADC, SUB, SBC, CP + ; + + default : + F_Out[Flag_P] = ~(^Q_t); + endcase // case(ALU_Op[2:0]) + + if (Arith16 == 1'b1 ) + begin + 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 + end // case: 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 + + 4'b1100 : + begin + // DAA + F_Out[Flag_H] = F_In[Flag_H]; + F_Out[Flag_C] = F_In[Flag_C]; + DAA_Q[7:0] = BusA; + DAA_Q[8] = 1'b0; + if (F_In[Flag_N] == 1'b0 ) + begin + // After addition + // Alow > 9 || H == 1 + if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) + begin + if ((DAA_Q[3:0] > 9) ) + begin + F_Out[Flag_H] = 1'b1; + end + else + begin + F_Out[Flag_H] = 1'b0; + end + DAA_Q = DAA_Q + 6; + end // if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) + + // new Ahigh > 9 || C == 1 + if (DAA_Q[8:4] > 9 || F_In[Flag_C] == 1'b1 ) + begin + DAA_Q = DAA_Q + 96; // 0x60 + end + end + else + begin + // After subtraction + if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) + begin + if (DAA_Q[3:0] > 5 ) + begin + F_Out[Flag_H] = 1'b0; + end + DAA_Q[7:0] = DAA_Q[7:0] - 6; + end + if (BusA > 153 || F_In[Flag_C] == 1'b1 ) + begin + DAA_Q = DAA_Q - 352; // 0x160 + end + end // else: !if(F_In[Flag_N] == 1'b0 ) + + F_Out[Flag_X] = DAA_Q[3]; + F_Out[Flag_Y] = DAA_Q[5]; + F_Out[Flag_C] = F_In[Flag_C] || DAA_Q[8]; + Q_t = DAA_Q[7:0]; + + if (DAA_Q[7:0] == 8'b00000000 ) + begin + F_Out[Flag_Z] = 1'b1; + end + else + begin + F_Out[Flag_Z] = 1'b0; + end + + F_Out[Flag_S] = DAA_Q[7]; + F_Out[Flag_P] = ~ (^DAA_Q); + end // case: 4'b1100 + + 4'b1101, 4'b1110 : + begin + // RLD, RRD + Q_t[7:4] = BusA[7:4]; + if (ALU_Op[0] == 1'b1 ) + begin + Q_t[3:0] = BusB[7:4]; + end + else + begin + Q_t[3:0] = BusB[3:0]; + end + F_Out[Flag_H] = 1'b0; + F_Out[Flag_N] = 1'b0; + F_Out[Flag_X] = Q_t[3]; + F_Out[Flag_Y] = Q_t[5]; + if (Q_t[7:0] == 8'b00000000 ) + begin + F_Out[Flag_Z] = 1'b1; + end + else + begin + F_Out[Flag_Z] = 1'b0; + end + F_Out[Flag_S] = Q_t[7]; + F_Out[Flag_P] = ~(^Q_t); + end // case: when 4'b1101, 4'b1110 + + 4'b1001 : + begin + // BIT + Q_t[7:0] = BusB & BitMask; + F_Out[Flag_S] = Q_t[7]; + if (Q_t[7:0] == 8'b00000000 ) + begin + F_Out[Flag_Z] = 1'b1; + F_Out[Flag_P] = 1'b1; + end + else + begin + F_Out[Flag_Z] = 1'b0; + F_Out[Flag_P] = 1'b0; + end + F_Out[Flag_H] = 1'b1; + F_Out[Flag_N] = 1'b0; + F_Out[Flag_X] = 1'b0; + F_Out[Flag_Y] = 1'b0; + if (IR[2:0] != 3'b110 ) + begin + F_Out[Flag_X] = BusB[3]; + F_Out[Flag_Y] = BusB[5]; + end + end // case: when 4'b1001 + + 4'b1010 : + // SET + Q_t[7:0] = BusB | BitMask; + + 4'b1011 : + // RES + Q_t[7:0] = BusB & ~ BitMask; + + 4'b1000 : + begin + // ROT + case (IR[5:3]) + 3'b000 : // RLC + begin + Q_t[7:1] = BusA[6:0]; + Q_t[0] = BusA[7]; + F_Out[Flag_C] = BusA[7]; + end + + 3'b010 : // RL + begin + Q_t[7:1] = BusA[6:0]; + Q_t[0] = F_In[Flag_C]; + F_Out[Flag_C] = BusA[7]; + end + + 3'b001 : // RRC + begin + Q_t[6:0] = BusA[7:1]; + Q_t[7] = BusA[0]; + F_Out[Flag_C] = BusA[0]; + end + + 3'b011 : // RR + begin + Q_t[6:0] = BusA[7:1]; + Q_t[7] = F_In[Flag_C]; + F_Out[Flag_C] = BusA[0]; + end + + 3'b100 : // SLA + begin + Q_t[7:1] = BusA[6:0]; + Q_t[0] = 1'b0; + F_Out[Flag_C] = BusA[7]; + end + + 3'b110 : // SLL (Undocumented) / SWAP + begin + if (Mode == 3 ) + begin + Q_t[7:4] = BusA[3:0]; + Q_t[3:0] = BusA[7:4]; + F_Out[Flag_C] = 1'b0; + end + else + begin + Q_t[7:1] = BusA[6:0]; + Q_t[0] = 1'b1; + F_Out[Flag_C] = BusA[7]; + end // else: !if(Mode == 3 ) + end // case: 3'b110 + + 3'b101 : // SRA + begin + Q_t[6:0] = BusA[7:1]; + Q_t[7] = BusA[7]; + F_Out[Flag_C] = BusA[0]; + end + + default : // SRL + begin + Q_t[6:0] = BusA[7:1]; + Q_t[7] = 1'b0; + F_Out[Flag_C] = BusA[0]; + end + endcase // case(IR[5:3]) + + F_Out[Flag_H] = 1'b0; + F_Out[Flag_N] = 1'b0; + 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:0] == 8'b00000000 ) + begin + F_Out[Flag_Z] = 1'b1; + end + else + begin + F_Out[Flag_Z] = 1'b0; + end + F_Out[Flag_P] = ~(^Q_t); + + if (ISet == 2'b00 ) + begin + 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 + end // case: 4'b1000 + + + default : + ; + + endcase // case(ALU_Op) + + Q = Q_t; + end // always @ (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + +endmodule // T80_ALU diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v new file mode 100644 index 000000000..1d69f791a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v @@ -0,0 +1,1304 @@ +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80_core (/*AUTOARG*/ + // Outputs + m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, do, mc, ts, + intcycle_n, IntE, stop, + // Inputs + reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, dinst, di + ); + // Beginning of automatic inputs (from unused autoinst inputs) + // End of automatics + + parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + parameter IOWait = 1; // 1 => Single cycle I/O, 1 => Std I/O cycle + parameter Flag_C = 0; + parameter Flag_N = 1; + parameter Flag_P = 2; + parameter Flag_X = 3; + parameter Flag_H = 4; + parameter Flag_Y = 5; + parameter Flag_Z = 6; + parameter Flag_S = 7; + + input reset_n; + input clk; + input cen; + input wait_n; + input int_n; + input nmi_n; + input busrq_n; + output m1_n; + output iorq; + output no_read; + output write; + output rfsh_n; + output halt_n; + output busak_n; + output [15:0] A; + input [7:0] dinst; + input [7:0] di; + output [7:0] do; + output [2:0] mc; + output [2:0] ts; + output intcycle_n; + output IntE; + output stop; + + reg m1_n; + reg iorq; + reg rfsh_n; + reg halt_n; + reg busak_n; + reg [15:0] A; + reg [7:0] do; + reg [2:0] mc; + reg [2:0] ts; + reg intcycle_n; + reg IntE; + reg stop; + + parameter aNone = 3'b111; + parameter aBC = 3'b000; + parameter aDE = 3'b001; + parameter aXY = 3'b010; + parameter aIOA = 3'b100; + parameter aSP = 3'b101; + parameter aZI = 3'b110; + + // Registers + reg [7:0] ACC, F; + reg [7:0] Ap, Fp; + reg [7:0] I; + reg [7:0] R; + reg [15:0] SP, PC; + reg [7:0] RegDIH; + reg [7:0] RegDIL; + wire [15:0] RegBusA; + wire [15:0] RegBusB; + wire [15:0] RegBusC; + reg [2:0] RegAddrA_r; + reg [2:0] RegAddrA; + reg [2:0] RegAddrB_r; + reg [2:0] RegAddrB; + reg [2:0] RegAddrC; + reg RegWEH; + reg RegWEL; + reg Alternate; + + // Help Registers + reg [15:0] TmpAddr; // Temporary address register + reg [7:0] IR; // Instruction register + reg [1:0] ISet; // Instruction set selector + reg [15:0] RegBusA_r; + + reg [15:0] ID16; + reg [7:0] Save_Mux; + + reg [2:0] tstate; + reg [2:0] mcycle; + reg IntE_FF1; + reg IntE_FF2; + reg Halt_FF; + reg BusReq_s; + reg BusAck; + reg ClkEn; + reg NMI_s; + reg INT_s; + reg [1:0] IStatus; + + reg [7:0] DI_Reg; + reg T_Res; + reg [1:0] XY_State; + reg [2:0] Pre_XY_F_M; + reg NextIs_XY_Fetch; + reg XY_Ind; + reg No_BTR; + reg BTR_r; + reg Auto_Wait; + reg Auto_Wait_t1; + reg Auto_Wait_t2; + reg IncDecZ; + + // ALU signals + reg [7:0] BusB; + reg [7:0] BusA; + wire [7:0] ALU_Q; + wire [7:0] F_Out; + + // Registered micro code outputs + reg [4:0] Read_To_Reg_r; + reg Arith16_r; + reg Z16_r; + reg [3:0] ALU_Op_r; + reg Save_ALU_r; + reg PreserveC_r; + reg [2:0] mcycles; + + // Micro code outputs + wire [2:0] mcycles_d; + wire [2:0] tstates; + reg IntCycle; + reg NMICycle; + wire Inc_PC; + wire Inc_WZ; + wire [3:0] IncDec_16; + wire [1:0] Prefix; + wire Read_To_Acc; + wire Read_To_Reg; + wire [3:0] Set_BusB_To; + wire [3:0] Set_BusA_To; + wire [3:0] ALU_Op; + wire Save_ALU; + wire PreserveC; + wire Arith16; + wire [2:0] Set_Addr_To; + wire Jump; + wire JumpE; + wire JumpXY; + wire Call; + wire RstP; + wire LDZ; + wire LDW; + wire LDSPHL; + wire iorq_i; + wire [2:0] Special_LD; + wire ExchangeDH; + wire ExchangeRp; + wire ExchangeAF; + wire ExchangeRS; + wire I_DJNZ; + wire I_CPL; + wire I_CCF; + wire I_SCF; + wire I_RETN; + wire I_BT; + wire I_BC; + wire I_BTR; + wire I_RLD; + wire I_RRD; + wire I_INRC; + wire SetDI; + wire SetEI; + wire [1:0] IMode; + wire Halt; + + reg [15:0] PC16; + reg [15:0] PC16_B; + reg [15:0] SP16, SP16_A, SP16_B; + reg [15:0] ID16_B; + reg Oldnmi_n; + + tv80_mcode #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_mcode + ( + .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 (no_read), + .Write (write) + ); + + tv80_alu #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_alu + ( + .Arith16 (Arith16_r), + .Z16 (Z16_r), + .ALU_Op (ALU_Op_r), + .IR (IR[5:0]), + .ISet (ISet), + .BusA (BusA), + .BusB (BusB), + .F_In (F), + .Q (ALU_Q), + .F_Out (F_Out) + ); + + always @(/*AUTOSENSE*/ALU_Q or BusAck or BusB or DI_Reg + or ExchangeRp or IR or Save_ALU_r or Set_Addr_To or XY_Ind + or XY_State or cen or mcycle or tstate or tstates) + begin + ClkEn = cen && ~ BusAck; + + if (tstate == tstates) + T_Res = 1'b1; + else T_Res = 1'b0; + + if (XY_State != 2'b00 && XY_Ind == 1'b0 && + ((Set_Addr_To == aXY) || + (mcycle == 3'b001 && IR == 8'b11001011) || + (mcycle == 3'b001 && IR == 8'b00110110))) + NextIs_XY_Fetch = 1'b1; + else + NextIs_XY_Fetch = 1'b0; + + if (ExchangeRp) + Save_Mux = BusB; + else if (!Save_ALU_r) + Save_Mux = DI_Reg; + else + Save_Mux = ALU_Q; + end // always @ * + + always @ (posedge clk) + begin + if (reset_n == 1'b0 ) + begin + PC <= #1 0; // Program Counter + A <= #1 0; + TmpAddr <= #1 0; + IR <= #1 8'b00000000; + ISet <= #1 2'b00; + XY_State <= #1 2'b00; + IStatus <= #1 2'b00; + mcycles <= #1 3'b000; + do <= #1 8'b00000000; + + ACC <= #1 8'hFF; + F <= #1 8'hFF; + Ap <= #1 8'hFF; + Fp <= #1 8'hFF; + I <= #1 0; + R <= #1 0; + SP <= #1 16'hFFFF; + Alternate <= #1 1'b0; + + Read_To_Reg_r <= #1 5'b00000; + Arith16_r <= #1 1'b0; + BTR_r <= #1 1'b0; + Z16_r <= #1 1'b0; + ALU_Op_r <= #1 4'b0000; + Save_ALU_r <= #1 1'b0; + PreserveC_r <= #1 1'b0; + XY_Ind <= #1 1'b0; + end + else + begin + + if (ClkEn == 1'b1 ) + begin + + ALU_Op_r <= #1 4'b0000; + Save_ALU_r <= #1 1'b0; + Read_To_Reg_r <= #1 5'b00000; + + mcycles <= #1 mcycles_d; + + if (IMode != 2'b11 ) + begin + IStatus <= #1 IMode; + end + + Arith16_r <= #1 Arith16; + PreserveC_r <= #1 PreserveC; + if (ISet == 2'b10 && ALU_Op[2] == 1'b0 && ALU_Op[0] == 1'b1 && mcycle == 3'b011 ) + begin + Z16_r <= #1 1'b1; + end + else + begin + Z16_r <= #1 1'b0; + end + + if (mcycle == 3'b001 && tstate[2] == 1'b0 ) + begin + // mcycle == 1 && tstate == 1, 2, || 3 + + if (tstate == 2 && wait_n == 1'b1 ) + begin + if (Mode < 2 ) + begin + A[7:0] <= #1 R; + A[15:8] <= #1 I; + R[6:0] <= #1 R[6:0] + 1; + end + + if (Jump == 1'b0 && Call == 1'b0 && NMICycle == 1'b0 && IntCycle == 1'b0 && ~ (Halt_FF == 1'b1 || Halt == 1'b1) ) + begin + PC <= #1 PC16; + end + + if (IntCycle == 1'b1 && IStatus == 2'b01 ) + begin + IR <= #1 8'b11111111; + end + else if (Halt_FF == 1'b1 || (IntCycle == 1'b1 && IStatus == 2'b10) || NMICycle == 1'b1 ) + begin + IR <= #1 8'b00000000; + end + else + begin + IR <= #1 dinst; + end + + ISet <= #1 2'b00; + if (Prefix != 2'b00 ) + begin + if (Prefix == 2'b11 ) + begin + if (IR[5] == 1'b1 ) + begin + XY_State <= #1 2'b10; + end + else + begin + XY_State <= #1 2'b01; + end + end + else + begin + if (Prefix == 2'b10 ) + begin + XY_State <= #1 2'b00; + XY_Ind <= #1 1'b0; + end + ISet <= #1 Prefix; + end + end + else + begin + XY_State <= #1 2'b00; + XY_Ind <= #1 1'b0; + end + end // if (tstate == 2 && wait_n == 1'b1 ) + + + end + else + begin + // either (mcycle > 1) OR (mcycle == 1 AND tstate > 3) + + if (mcycle == 3'b110 ) + begin + XY_Ind <= #1 1'b1; + if (Prefix == 2'b01 ) + begin + ISet <= #1 2'b01; + end + end + + if (T_Res == 1'b1 ) + begin + BTR_r <= #1 (I_BT || I_BC || I_BTR) && ~ No_BTR; + if (Jump == 1'b1 ) + begin + A[15:8] <= #1 DI_Reg; + A[7:0] <= #1 TmpAddr[7:0]; + PC[15:8] <= #1 DI_Reg; + PC[7:0] <= #1 TmpAddr[7:0]; + end + else if (JumpXY == 1'b1 ) + begin + A <= #1 RegBusC; + PC <= #1 RegBusC; + end else if (Call == 1'b1 || RstP == 1'b1 ) + begin + A <= #1 TmpAddr; + PC <= #1 TmpAddr; + end + else if (mcycle == mcycles && NMICycle == 1'b1 ) + begin + A <= #1 16'b0000000001100110; + PC <= #1 16'b0000000001100110; + end + else if (mcycle == 3'b011 && IntCycle == 1'b1 && IStatus == 2'b10 ) + begin + A[15:8] <= #1 I; + A[7:0] <= #1 TmpAddr[7:0]; + PC[15:8] <= #1 I; + PC[7:0] <= #1 TmpAddr[7:0]; + end + else + begin + case (Set_Addr_To) + aXY : + begin + if (XY_State == 2'b00 ) + begin + A <= #1 RegBusC; + end + else + begin + if (NextIs_XY_Fetch == 1'b1 ) + begin + A <= #1 PC; + end + else + begin + A <= #1 TmpAddr; + end + end // else: !if(XY_State == 2'b00 ) + end // case: aXY + + aIOA : + begin + if (Mode == 3 ) + begin + // Memory map I/O on GBZ80 + A[15:8] <= #1 8'hFF; + end + else if (Mode == 2 ) + begin + // Duplicate I/O address on 8080 + A[15:8] <= #1 DI_Reg; + end + else + begin + A[15:8] <= #1 ACC; + end + A[7:0] <= #1 DI_Reg; + end // case: aIOA + + + aSP : + begin + A <= #1 SP; + end + + aBC : + begin + if (Mode == 3 && iorq_i == 1'b1 ) + begin + // Memory map I/O on GBZ80 + A[15:8] <= #1 8'hFF; + A[7:0] <= #1 RegBusC[7:0]; + end + else + begin + A <= #1 RegBusC; + end + end // case: aBC + + aDE : + begin + A <= #1 RegBusC; + end + + aZI : + begin + if (Inc_WZ == 1'b1 ) + begin + A <= #1 TmpAddr + 1; + end + else + begin + A[15:8] <= #1 DI_Reg; + A[7:0] <= #1 TmpAddr[7:0]; + end + end // case: aZI + + default : + begin + A <= #1 PC; + end + endcase // case(Set_Addr_To) + + end // else: !if(mcycle == 3'b011 && IntCycle == 1'b1 && IStatus == 2'b10 ) + + + Save_ALU_r <= #1 Save_ALU; + ALU_Op_r <= #1 ALU_Op; + + if (I_CPL == 1'b1 ) + begin + // CPL + ACC <= #1 ~ ACC; + F[Flag_Y] <= #1 ~ ACC[5]; + F[Flag_H] <= #1 1'b1; + F[Flag_X] <= #1 ~ ACC[3]; + F[Flag_N] <= #1 1'b1; + end + if (I_CCF == 1'b1 ) + begin + // CCF + F[Flag_C] <= #1 ~ F[Flag_C]; + F[Flag_Y] <= #1 ACC[5]; + F[Flag_H] <= #1 F[Flag_C]; + F[Flag_X] <= #1 ACC[3]; + F[Flag_N] <= #1 1'b0; + end + if (I_SCF == 1'b1 ) + begin + // SCF + F[Flag_C] <= #1 1'b1; + F[Flag_Y] <= #1 ACC[5]; + F[Flag_H] <= #1 1'b0; + F[Flag_X] <= #1 ACC[3]; + F[Flag_N] <= #1 1'b0; + end + end // if (T_Res == 1'b1 ) + + + if (tstate == 2 && wait_n == 1'b1 ) + begin + if (ISet == 2'b01 && mcycle == 3'b111 ) + begin + IR <= #1 dinst; + end + if (JumpE == 1'b1 ) + begin + PC <= #1 PC16; + end + else if (Inc_PC == 1'b1 ) + begin + //PC <= #1 PC + 1; + PC <= #1 PC16; + end + if (BTR_r == 1'b1 ) + begin + //PC <= #1 PC - 2; + PC <= #1 PC16; + end + if (RstP == 1'b1 ) + begin + TmpAddr <= #1 { 10'h0, IR[5:3], 3'h0 }; + //TmpAddr <= #1 (others =>1'b0); + //TmpAddr[5:3] <= #1 IR[5:3]; + end + end + if (tstate == 3 && mcycle == 3'b110 ) + begin + TmpAddr <= #1 SP16; + end + + if ((tstate == 2 && wait_n == 1'b1) || (tstate == 4 && mcycle == 3'b001) ) + begin + if (IncDec_16[2:0] == 3'b111 ) + begin + SP <= #1 SP16; + end + end + + if (LDSPHL == 1'b1 ) + begin + SP <= #1 RegBusC; + end + if (ExchangeAF == 1'b1 ) + begin + Ap <= #1 ACC; + ACC <= #1 Ap; + Fp <= #1 F; + F <= #1 Fp; + end + if (ExchangeRS == 1'b1 ) + begin + Alternate <= #1 ~ Alternate; + end + end // else: !if(mcycle == 3'b001 && tstate(2) == 1'b0 ) + + + if (tstate == 3 ) + begin + if (LDZ == 1'b1 ) + begin + TmpAddr[7:0] <= #1 DI_Reg; + end + if (LDW == 1'b1 ) + begin + TmpAddr[15:8] <= #1 DI_Reg; + end + + if (Special_LD[2] == 1'b1 ) + begin + case (Special_LD[1:0]) + 2'b00 : + begin + ACC <= #1 I; + F[Flag_P] <= #1 IntE_FF2; + end + + 2'b01 : + begin + ACC <= #1 R; + F[Flag_P] <= #1 IntE_FF2; + end + + 2'b10 : + I <= #1 ACC; + + default : + R <= #1 ACC; + endcase + end + end // if (tstate == 3 ) + + + if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 ) + begin + if (Mode == 3 ) + begin + F[6] <= #1 F_Out[6]; + F[5] <= #1 F_Out[5]; + F[7] <= #1 F_Out[7]; + if (PreserveC_r == 1'b0 ) + begin + F[4] <= #1 F_Out[4]; + end + end + else + begin + F[7:1] <= #1 F_Out[7:1]; + if (PreserveC_r == 1'b0 ) + begin + F[Flag_C] <= #1 F_Out[0]; + end + end + end // if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 ) + + if (T_Res == 1'b1 && I_INRC == 1'b1 ) + begin + F[Flag_H] <= #1 1'b0; + F[Flag_N] <= #1 1'b0; + if (DI_Reg[7:0] == 8'b00000000 ) + begin + F[Flag_Z] <= #1 1'b1; + end + else + begin + F[Flag_Z] <= #1 1'b0; + end + F[Flag_S] <= #1 DI_Reg[7]; + F[Flag_P] <= #1 ~ (^DI_Reg[7:0]); + end // if (T_Res == 1'b1 && I_INRC == 1'b1 ) + + + if (tstate == 1 && Auto_Wait_t1 == 1'b0 ) + begin + do <= #1 BusB; + if (I_RLD == 1'b1 ) + begin + do[3:0] <= #1 BusA[3:0]; + do[7:4] <= #1 BusB[3:0]; + end + if (I_RRD == 1'b1 ) + begin + do[3:0] <= #1 BusB[7:4]; + do[7:4] <= #1 BusA[3:0]; + end + end + + if (T_Res == 1'b1 ) + begin + Read_To_Reg_r[3:0] <= #1 Set_BusA_To; + Read_To_Reg_r[4] <= #1 Read_To_Reg; + if (Read_To_Acc == 1'b1 ) + begin + Read_To_Reg_r[3:0] <= #1 4'b0111; + Read_To_Reg_r[4] <= #1 1'b1; + end + end + + if (tstate == 1 && I_BT == 1'b1 ) + begin + F[Flag_X] <= #1 ALU_Q[3]; + F[Flag_Y] <= #1 ALU_Q[1]; + F[Flag_H] <= #1 1'b0; + F[Flag_N] <= #1 1'b0; + end + if (I_BC == 1'b1 || I_BT == 1'b1 ) + begin + F[Flag_P] <= #1 IncDecZ; + end + + if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) || + (Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) ) + begin + case (Read_To_Reg_r) + 5'b10111 : + ACC <= #1 Save_Mux; + 5'b10110 : + do <= #1 Save_Mux; + 5'b11000 : + SP[7:0] <= #1 Save_Mux; + 5'b11001 : + SP[15:8] <= #1 Save_Mux; + 5'b11011 : + F <= #1 Save_Mux; + endcase + end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||... + end // if (ClkEn == 1'b1 ) + end // else: !if(reset_n == 1'b0 ) + end + + + //------------------------------------------------------------------------- + // + // BC('), DE('), HL('), IX && IY + // + //------------------------------------------------------------------------- + always @ (posedge clk) + begin + if (ClkEn == 1'b1 ) + begin + // Bus A / Write + RegAddrA_r <= #1 { Alternate, Set_BusA_To[2:1] }; + if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusA_To[2:1] == 2'b10 ) + begin + RegAddrA_r <= #1 { XY_State[1], 2'b11 }; + end + + // Bus B + RegAddrB_r <= #1 { Alternate, Set_BusB_To[2:1] }; + if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusB_To[2:1] == 2'b10 ) + begin + RegAddrB_r <= #1 { XY_State[1], 2'b11 }; + end + + // Address from register + RegAddrC <= #1 { Alternate, Set_Addr_To[1:0] }; + // Jump (HL), LD SP,HL + if ((JumpXY == 1'b1 || LDSPHL == 1'b1) ) + begin + RegAddrC <= #1 { Alternate, 2'b10 }; + end + if (((JumpXY == 1'b1 || LDSPHL == 1'b1) && XY_State != 2'b00) || (mcycle == 3'b110) ) + begin + RegAddrC <= #1 { XY_State[1], 2'b11 }; + end + + if (I_DJNZ == 1'b1 && Save_ALU_r == 1'b1 && Mode < 2 ) + begin + IncDecZ <= #1 F_Out[Flag_Z]; + end + if ((tstate == 2 || (tstate == 3 && mcycle == 3'b001)) && IncDec_16[2:0] == 3'b100 ) + begin + if (ID16 == 0 ) + begin + IncDecZ <= #1 1'b0; + end + else + begin + IncDecZ <= #1 1'b1; + end + end + + RegBusA_r <= #1 RegBusA; + end + + end // always @ (posedge clk) + + + always @(/*AUTOSENSE*/Alternate or ExchangeDH or IncDec_16 + or RegAddrA_r or RegAddrB_r or XY_State or mcycle or tstate) + begin + if ((tstate == 2 || (tstate == 3 && mcycle == 3'b001 && IncDec_16[2] == 1'b1)) && XY_State == 2'b00) + RegAddrA = { Alternate, IncDec_16[1:0] }; + else if ((tstate == 2 || (tstate == 3 && mcycle == 3'b001 && IncDec_16[2] == 1'b1)) && IncDec_16[1:0] == 2'b10) + RegAddrA = { XY_State[1], 2'b11 }; + else if (ExchangeDH == 1'b1 && tstate == 3) + RegAddrA = { Alternate, 2'b10 }; + else if (ExchangeDH == 1'b1 && tstate == 4) + RegAddrA = { Alternate, 2'b01 }; + else + RegAddrA = RegAddrA_r; + + if (ExchangeDH == 1'b1 && tstate == 3) + RegAddrB = { Alternate, 2'b01 }; + else + RegAddrB = RegAddrB_r; + end // always @ * + + + always @(/*AUTOSENSE*/ALU_Op_r or Auto_Wait_t1 or ExchangeDH + or IncDec_16 or Read_To_Reg_r or Save_ALU_r or mcycle + or tstate or wait_n) + begin + RegWEH = 1'b0; + RegWEL = 1'b0; + if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) || + (Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) ) + begin + case (Read_To_Reg_r) + 5'b10000 , 5'b10001 , 5'b10010 , 5'b10011 , 5'b10100 , 5'b10101 : + begin + RegWEH = ~ Read_To_Reg_r[0]; + RegWEL = Read_To_Reg_r[0]; + end + endcase // case(Read_To_Reg_r) + + end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||... + + + if (ExchangeDH == 1'b1 && (tstate == 3 || tstate == 4) ) + begin + RegWEH = 1'b1; + RegWEL = 1'b1; + end + + if (IncDec_16[2] == 1'b1 && ((tstate == 2 && wait_n == 1'b1 && mcycle != 3'b001) || (tstate == 3 && mcycle == 3'b001)) ) + begin + case (IncDec_16[1:0]) + 2'b00 , 2'b01 , 2'b10 : + begin + RegWEH = 1'b1; + RegWEL = 1'b1; + end + endcase + end + end // always @ * + + + always @(/*AUTOSENSE*/ExchangeDH or ID16 or IncDec_16 or RegBusA_r + or RegBusB or Save_Mux or mcycle or tstate) + begin + RegDIH = Save_Mux; + RegDIL = Save_Mux; + + if (ExchangeDH == 1'b1 && tstate == 3 ) + begin + RegDIH = RegBusB[15:8]; + RegDIL = RegBusB[7:0]; + end + else if (ExchangeDH == 1'b1 && tstate == 4 ) + begin + RegDIH = RegBusA_r[15:8]; + RegDIL = RegBusA_r[7:0]; + end + else if (IncDec_16[2] == 1'b1 && ((tstate == 2 && mcycle != 3'b001) || (tstate == 3 && mcycle == 3'b001)) ) + begin + RegDIH = ID16[15:8]; + RegDIL = ID16[7:0]; + end + end + + tv80_reg i_reg + ( + .clk (clk), + .CEN (ClkEn), + .WEH (RegWEH), + .WEL (RegWEL), + .AddrA (RegAddrA), + .AddrB (RegAddrB), + .AddrC (RegAddrC), + .DIH (RegDIH), + .DIL (RegDIL), + .DOAH (RegBusA[15:8]), + .DOAL (RegBusA[7:0]), + .DOBH (RegBusB[15:8]), + .DOBL (RegBusB[7:0]), + .DOCH (RegBusC[15:8]), + .DOCL (RegBusC[7:0]) + ); + + //------------------------------------------------------------------------- + // + // Buses + // + //------------------------------------------------------------------------- + + always @ (posedge clk) + begin + if (ClkEn == 1'b1 ) + begin + case (Set_BusB_To) + 4'b0111 : + BusB <= #1 ACC; + 4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 : + begin + if (Set_BusB_To[0] == 1'b1 ) + begin + BusB <= #1 RegBusB[7:0]; + end + else + begin + BusB <= #1 RegBusB[15:8]; + end + end + 4'b0110 : + BusB <= #1 DI_Reg; + 4'b1000 : + BusB <= #1 SP[7:0]; + 4'b1001 : + BusB <= #1 SP[15:8]; + 4'b1010 : + BusB <= #1 8'b00000001; + 4'b1011 : + BusB <= #1 F; + 4'b1100 : + BusB <= #1 PC[7:0]; + 4'b1101 : + BusB <= #1 PC[15:8]; + 4'b1110 : + BusB <= #1 8'b00000000; + default : + BusB <= #1 8'hxx; + endcase + + case (Set_BusA_To) + 4'b0111 : + BusA <= #1 ACC; + 4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 : + begin + if (Set_BusA_To[0] == 1'b1 ) + begin + BusA <= #1 RegBusA[7:0]; + end + else + begin + BusA <= #1 RegBusA[15:8]; + end + end + 4'b0110 : + BusA <= #1 DI_Reg; + 4'b1000 : + BusA <= #1 SP[7:0]; + 4'b1001 : + BusA <= #1 SP[15:8]; + 4'b1010 : + BusA <= #1 8'b00000000; + default : + BusB <= #1 8'hxx; + endcase + end + end + + //------------------------------------------------------------------------- + // + // Generate external control signals + // + //------------------------------------------------------------------------- + always @ (posedge clk) + begin + if (reset_n == 1'b0 ) + begin + rfsh_n <= #1 1'b1; + end + else + begin + if (cen == 1'b1 ) + begin + if (mcycle == 3'b001 && ((tstate == 2 && wait_n == 1'b1) || tstate == 3) ) + begin + rfsh_n <= #1 1'b0; + end + else + begin + rfsh_n <= #1 1'b1; + end + end + end + end + + + always @(/*AUTOSENSE*/BusAck or Halt_FF or I_DJNZ or IntCycle + or IntE_FF1 or di or iorq_i or mcycle or tstate) + begin + mc = mcycle; + ts = tstate; + DI_Reg = di; + halt_n = ~ Halt_FF; + busak_n = ~ BusAck; + intcycle_n = ~ IntCycle; + IntE = IntE_FF1; + iorq = iorq_i; + stop = I_DJNZ; + end + + //----------------------------------------------------------------------- + // + // Syncronise inputs + // + //----------------------------------------------------------------------- + + always @ (posedge clk) + begin : sync_inputs + + if (reset_n == 1'b0 ) + begin + BusReq_s <= #1 1'b0; + INT_s <= #1 1'b0; + NMI_s <= #1 1'b0; + Oldnmi_n <= #1 1'b0; + end + else + begin + if (cen == 1'b1 ) + begin + BusReq_s <= #1 ~ busrq_n; + INT_s <= #1 ~ int_n; + if (NMICycle == 1'b1 ) + begin + NMI_s <= #1 1'b0; + end + else if (nmi_n == 1'b0 && Oldnmi_n == 1'b1 ) + begin + NMI_s <= #1 1'b1; + end + Oldnmi_n <= #1 nmi_n; + end + end + end + + //----------------------------------------------------------------------- + // + // Main state machine + // + //----------------------------------------------------------------------- + + always @ (posedge clk) + begin + if (reset_n == 1'b0 ) + begin + mcycle <= #1 3'b001; + tstate <= #1 3'b000; + Pre_XY_F_M <= #1 3'b000; + Halt_FF <= #1 1'b0; + BusAck <= #1 1'b0; + NMICycle <= #1 1'b0; + IntCycle <= #1 1'b0; + IntE_FF1 <= #1 1'b0; + IntE_FF2 <= #1 1'b0; + No_BTR <= #1 1'b0; + Auto_Wait_t1 <= #1 1'b0; + Auto_Wait_t2 <= #1 1'b0; + m1_n <= #1 1'b1; + end + else + begin + if (cen == 1'b1 ) + begin + if (T_Res == 1'b1 ) + begin + Auto_Wait_t1 <= #1 1'b0; + end + else + begin + Auto_Wait_t1 <= #1 Auto_Wait || iorq_i; + end + Auto_Wait_t2 <= #1 Auto_Wait_t1; + No_BTR <= #1 (I_BT && (~ IR[4] || ~ F[Flag_P])) || + (I_BC && (~ IR[4] || F[Flag_Z] || ~ F[Flag_P])) || + (I_BTR && (~ IR[4] || F[Flag_Z])); + if (tstate == 2 ) + begin + if (SetEI == 1'b1 ) + begin + IntE_FF1 <= #1 1'b1; + IntE_FF2 <= #1 1'b1; + end + if (I_RETN == 1'b1 ) + begin + IntE_FF1 <= #1 IntE_FF2; + end + end + if (tstate == 3 ) + begin + if (SetDI == 1'b1 ) + begin + IntE_FF1 <= #1 1'b0; + IntE_FF2 <= #1 1'b0; + end + end + if (IntCycle == 1'b1 || NMICycle == 1'b1 ) + begin + Halt_FF <= #1 1'b0; + end + if (mcycle == 3'b001 && tstate == 2 && wait_n == 1'b1 ) + begin + m1_n <= #1 1'b1; + end + if (BusReq_s == 1'b1 && BusAck == 1'b1 ) + begin + end + else + begin + BusAck <= #1 1'b0; + if (tstate == 2 && wait_n == 1'b0 ) + begin + end + else if (T_Res == 1'b1 ) + begin + if (Halt == 1'b1 ) + begin + Halt_FF <= #1 1'b1; + end + if (BusReq_s == 1'b1 ) + begin + BusAck <= #1 1'b1; + end + else + begin + tstate <= #1 3'b001; + if (NextIs_XY_Fetch == 1'b1 ) + begin + mcycle <= #1 3'b110; + Pre_XY_F_M <= #1 mcycle; + if (IR == 8'b00110110 && Mode == 0 ) + begin + Pre_XY_F_M <= #1 3'b010; + end + end + else if ((mcycle == 3'b111) || (mcycle == 3'b110 && Mode == 1 && ISet != 2'b01) ) + begin + mcycle <= #1 Pre_XY_F_M + 1; + end + else if ((mcycle == mcycles) || + No_BTR == 1'b1 || + (mcycle == 3'b010 && I_DJNZ == 1'b1 && IncDecZ == 1'b1) ) + begin + m1_n <= #1 1'b0; + mcycle <= #1 3'b001; + IntCycle <= #1 1'b0; + NMICycle <= #1 1'b0; + if (NMI_s == 1'b1 && Prefix == 2'b00 ) + begin + NMICycle <= #1 1'b1; + IntE_FF1 <= #1 1'b0; + end + else if ((IntE_FF1 == 1'b1 && INT_s == 1'b1) && Prefix == 2'b00 && SetEI == 1'b0 ) + begin + IntCycle <= #1 1'b1; + IntE_FF1 <= #1 1'b0; + IntE_FF2 <= #1 1'b0; + end + end + else + begin + mcycle <= #1 mcycle + 1; + end + end + end + else + begin // verilog has no "nor" operator + if ( ~(Auto_Wait == 1'b1 && Auto_Wait_t2 == 1'b0) && + ~(IOWait == 1 && iorq_i == 1'b1 && Auto_Wait_t1 == 1'b0) ) + begin + tstate <= #1 tstate + 1; + end + end + end + if (tstate == 0 ) + begin + m1_n <= #1 1'b0; + end + end + end + end + + always @(/*AUTOSENSE*/BTR_r or DI_Reg or IncDec_16 or JumpE or PC + or RegBusA or RegBusC or SP or tstate) + begin + if (JumpE == 1'b1 ) + begin + PC16_B = { {8{DI_Reg[7]}}, DI_Reg }; + end + else if (BTR_r == 1'b1 ) + begin + PC16_B = -2; + end + else + begin + PC16_B = 1; + end + + if (tstate == 3) + begin + SP16_A = RegBusC; + SP16_B = { {8{DI_Reg[7]}}, DI_Reg }; + end + else + begin + // suspect that ID16 and SP16 could be shared + SP16_A = SP; + + if (IncDec_16[3] == 1'b1) + SP16_B = -1; + else + SP16_B = 1; + end + + if (IncDec_16[3]) + ID16_B = -1; + else + ID16_B = 1; + + ID16 = RegBusA + ID16_B; + PC16 = PC + PC16_B; + SP16 = SP16_A + SP16_B; + end // always @ * + + + always @(/*AUTOSENSE*/IntCycle or NMICycle or mcycle) + begin + Auto_Wait = 1'b0; + if (IntCycle == 1'b1 || NMICycle == 1'b1 ) + begin + if (mcycle == 3'b001 ) + begin + Auto_Wait = 1'b1; + end + end + end // always @ * + +// synopsys dc_script_begin +// set_attribute current_design "revision" "$Id: tv80_core.v,v 1.1 2004/05/16 17:39:57 ghutchis Exp $" -type string -quiet +// synopsys dc_script_end +endmodule // T80 + diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v new file mode 100644 index 000000000..44e35f648 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v @@ -0,0 +1,2759 @@ +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80_mcode (/*AUTOARG*/ + // Outputs + MCycles, TStates, Prefix, Inc_PC, Inc_WZ, IncDec_16, Read_To_Reg, + Read_To_Acc, Set_BusA_To, Set_BusB_To, ALU_Op, Save_ALU, PreserveC, + Arith16, Set_Addr_To, IORQ, Jump, JumpE, JumpXY, Call, RstP, LDZ, + LDW, LDSPHL, Special_LD, ExchangeDH, ExchangeRp, ExchangeAF, + ExchangeRS, I_DJNZ, I_CPL, I_CCF, I_SCF, I_RETN, I_BT, I_BC, I_BTR, + I_RLD, I_RRD, I_INRC, SetDI, SetEI, IMode, Halt, NoRead, Write, + // Inputs + IR, ISet, MCycle, F, NMICycle, IntCycle + ); + + parameter Mode = 0; + parameter Flag_C = 0; + parameter Flag_N = 1; + parameter Flag_P = 2; + parameter Flag_X = 3; + parameter Flag_H = 4; + parameter Flag_Y = 5; + parameter Flag_Z = 6; + parameter Flag_S = 7; + + input [7:0] IR; + input [1:0] ISet ; + input [2:0] MCycle ; + input [7:0] F ; + input NMICycle ; + input IntCycle ; + output [2:0] MCycles ; + output [2:0] TStates ; + output [1:0] Prefix ; // None,BC,ED,DD/FD + output Inc_PC ; + output Inc_WZ ; + output [3:0] IncDec_16 ; // BC,DE,HL,SP 0 is inc + output Read_To_Reg ; + output Read_To_Acc ; + output [3:0] Set_BusA_To ; // B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + output [3:0] Set_BusB_To ; // B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + output [3:0] ALU_Op ; + output Save_ALU ; + output PreserveC ; + output Arith16 ; + output [2:0] Set_Addr_To ; // aNone,aXY,aIOA,aSP,aBC,aDE,aZI + output IORQ ; + output Jump ; + output JumpE ; + output JumpXY ; + output Call ; + output RstP ; + output LDZ ; + output LDW ; + output LDSPHL ; + output [2:0] Special_LD ; // A,I;A,R;I,A;R,A;None + output ExchangeDH ; + output ExchangeRp ; + output ExchangeAF ; + output ExchangeRS ; + output I_DJNZ ; + output I_CPL ; + output I_CCF ; + output I_SCF ; + output I_RETN ; + output I_BT ; + output I_BC ; + output I_BTR ; + output I_RLD ; + output I_RRD ; + output I_INRC ; + output SetDI ; + output SetEI ; + output [1:0] IMode ; + output Halt ; + output NoRead ; + output Write ; + + // regs + reg [2:0] MCycles ; + reg [2:0] TStates ; + reg [1:0] Prefix ; // None,BC,ED,DD/FD + reg Inc_PC ; + reg Inc_WZ ; + reg [3:0] IncDec_16 ; // BC,DE,HL,SP 0 is inc + reg Read_To_Reg ; + reg Read_To_Acc ; + reg [3:0] Set_BusA_To ; // B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + reg [3:0] Set_BusB_To ; // B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + reg [3:0] ALU_Op ; + reg Save_ALU ; + reg PreserveC ; + reg Arith16 ; + reg [2:0] Set_Addr_To ; // aNone,aXY,aIOA,aSP,aBC,aDE,aZI + reg IORQ ; + reg Jump ; + reg JumpE ; + reg JumpXY ; + reg Call ; + reg RstP ; + reg LDZ ; + reg LDW ; + reg LDSPHL ; + reg [2:0] Special_LD ; // A,I;A,R;I,A;R,A;None + reg ExchangeDH ; + reg ExchangeRp ; + reg ExchangeAF ; + reg ExchangeRS ; + reg I_DJNZ ; + reg I_CPL ; + reg I_CCF ; + reg I_SCF ; + reg I_RETN ; + reg I_BT ; + reg I_BC ; + reg I_BTR ; + reg I_RLD ; + reg I_RRD ; + reg I_INRC ; + reg SetDI ; + reg SetEI ; + reg [1:0] IMode ; + reg Halt ; + reg NoRead ; + reg Write ; + + parameter aNone = 3'b111; + parameter aBC = 3'b000; + parameter aDE = 3'b001; + parameter aXY = 3'b010; + parameter aIOA = 3'b100; + parameter aSP = 3'b101; + parameter aZI = 3'b110; +// constant aNone : std_logic_vector[2:0] = 3'b000; +// constant aXY : std_logic_vector[2:0] = 3'b001; +// constant aIOA : std_logic_vector[2:0] = 3'b010; +// constant aSP : std_logic_vector[2:0] = 3'b011; +// constant aBC : std_logic_vector[2:0] = 3'b100; +// constant aDE : std_logic_vector[2:0] = 3'b101; +// constant aZI : std_logic_vector[2:0] = 3'b110; + + function is_cc_true; + input [7:0] F; + input [2:0] cc; + begin + if (Mode == 3 ) + begin + case (cc) + 3'b000 : is_cc_true = F[7] == 1'b0; // NZ + 3'b001 : is_cc_true = F[7] == 1'b1; // Z + 3'b010 : is_cc_true = F[4] == 1'b0; // NC + 3'b011 : is_cc_true = F[4] == 1'b1; // C + 3'b100 : is_cc_true = 0; + 3'b101 : is_cc_true = 0; + 3'b110 : is_cc_true = 0; + 3'b111 : is_cc_true = 0; + endcase + end + else + begin + case (cc) + 3'b000 : is_cc_true = F[6] == 1'b0; // NZ + 3'b001 : is_cc_true = F[6] == 1'b1; // Z + 3'b010 : is_cc_true = F[0] == 1'b0; // NC + 3'b011 : is_cc_true = F[0] == 1'b1; // C + 3'b100 : is_cc_true = F[2] == 1'b0; // PO + 3'b101 : is_cc_true = F[2] == 1'b1; // PE + 3'b110 : is_cc_true = F[7] == 1'b0; // P + 3'b111 : is_cc_true = F[7] == 1'b1; // M + endcase + end + end + endfunction // is_cc_true + + + reg [2:0] DDD; + reg [2:0] SSS; + reg [1:0] DPAIR; + reg [7:0] IRB; + + always @ (/*AUTOSENSE*/F or IR or ISet or IntCycle or MCycle + or NMICycle) + begin + DDD = IR[5:3]; + SSS = IR[2:0]; + DPAIR = IR[5:4]; + IRB = IR; + + MCycles = 3'b001; + if (MCycle == 3'b001 ) + begin + TStates = 3'b100; + end + else + begin + TStates = 3'b011; + end + Prefix = 2'b00; + Inc_PC = 1'b0; + Inc_WZ = 1'b0; + IncDec_16 = 4'b0000; + Read_To_Acc = 1'b0; + Read_To_Reg = 1'b0; + Set_BusB_To = 4'b0000; + Set_BusA_To = 4'b0000; + ALU_Op = { 1'b0, IR[5:3] }; + Save_ALU = 1'b0; + PreserveC = 1'b0; + Arith16 = 1'b0; + IORQ = 1'b0; + Set_Addr_To = aNone; + Jump = 1'b0; + JumpE = 1'b0; + JumpXY = 1'b0; + Call = 1'b0; + RstP = 1'b0; + LDZ = 1'b0; + LDW = 1'b0; + LDSPHL = 1'b0; + Special_LD = 3'b000; + ExchangeDH = 1'b0; + ExchangeRp = 1'b0; + ExchangeAF = 1'b0; + ExchangeRS = 1'b0; + I_DJNZ = 1'b0; + I_CPL = 1'b0; + I_CCF = 1'b0; + I_SCF = 1'b0; + I_RETN = 1'b0; + I_BT = 1'b0; + I_BC = 1'b0; + I_BTR = 1'b0; + I_RLD = 1'b0; + I_RRD = 1'b0; + I_INRC = 1'b0; + SetDI = 1'b0; + SetEI = 1'b0; + IMode = 2'b11; + Halt = 1'b0; + NoRead = 1'b0; + Write = 1'b0; + + case (ISet) + 2'b00 : + begin + +//---------------------------------------------------------------------------- +// +// Unprefixed instructions +// +//---------------------------------------------------------------------------- + + case (IRB) +// 8 BIT LOAD GROUP + 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111, + 8'b01001000,8'b01001001,8'b01001010,8'b01001011,8'b01001100,8'b01001101,8'b01001111, + 8'b01010000,8'b01010001,8'b01010010,8'b01010011,8'b01010100,8'b01010101,8'b01010111, + 8'b01011000,8'b01011001,8'b01011010,8'b01011011,8'b01011100,8'b01011101,8'b01011111, + 8'b01100000,8'b01100001,8'b01100010,8'b01100011,8'b01100100,8'b01100101,8'b01100111, + 8'b01101000,8'b01101001,8'b01101010,8'b01101011,8'b01101100,8'b01101101,8'b01101111, + 8'b01111000,8'b01111001,8'b01111010,8'b01111011,8'b01111100,8'b01111101,8'b01111111 : + begin + + // LD r,r' + Set_BusB_To[2:0] = SSS; + ExchangeRp = 1'b1; + Set_BusA_To[2:0] = DDD; + Read_To_Reg = 1'b1; + end // case: 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111,... + + 8'b00000110,8'b00001110,8'b00010110,8'b00011110,8'b00100110,8'b00101110,8'b00111110 : + begin + // LD r,n + MCycles = 3'b010; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_BusA_To[2:0] = DDD; + Read_To_Reg = 1'b1; + end + default :; + endcase // case(MCycle) + end // case: 8'b00000110,8'b00001110,8'b00010110,8'b00011110,8'b00100110,8'b00101110,8'b00111110 + + 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01111110 : + begin + // LD r,(HL) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + Set_BusA_To[2:0] = DDD; + Read_To_Reg = 1'b1; + end + default :; + endcase // case(MCycle) + end // case: 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01111110 + + 8'b01110000,8'b01110001,8'b01110010,8'b01110011,8'b01110100,8'b01110101,8'b01110111 : + begin + // LD (HL),r + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aXY; + Set_BusB_To[2:0] = SSS; + Set_BusB_To[3] = 1'b0; + end + 2 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b01110000,8'b01110001,8'b01110010,8'b01110011,8'b01110100,8'b01110101,8'b01110111 + + 8'b00110110 : + begin + // LD (HL),n + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_Addr_To = aXY; + Set_BusB_To[2:0] = SSS; + Set_BusB_To[3] = 1'b0; + end + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00110110 + + 8'b00001010 : + begin + // LD A,(BC) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aBC; + 2 : + Read_To_Acc = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00001010 + + 8'b00011010 : + begin + // LD A,(DE) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aDE; + 2 : + Read_To_Acc = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00011010 + + 8'b00111010 : + begin + if (Mode == 3 ) + begin + // LDD A,(HL) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + Read_To_Acc = 1'b1; + IncDec_16 = 4'b1110; + end + default :; + endcase + end + else + begin + // LD A,(nn) + MCycles = 3'b100; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + end + 4 : + begin + Read_To_Acc = 1'b1; + end + default :; + endcase + end // else: !if(Mode == 3 ) + end // case: 8'b00111010 + + 8'b00000010 : + begin + // LD (BC),A + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aBC; + Set_BusB_To = 4'b0111; + end + 2 : + begin + Write = 1'b1; + end + default :; + endcase // case(MCycle) + end // case: 8'b00000010 + + 8'b00010010 : + begin + // LD (DE),A + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aDE; + Set_BusB_To = 4'b0111; + end + 2 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00010010 + + 8'b00110010 : + begin + if (Mode == 3 ) + begin + // LDD (HL),A + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aXY; + Set_BusB_To = 4'b0111; + end + 2 : + begin + Write = 1'b1; + IncDec_16 = 4'b1110; + end + default :; + endcase // case(MCycle) + + end + else + begin + // LD (nn),A + MCycles = 3'b100; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + Set_BusB_To = 4'b0111; + end + 4 : + begin + Write = 1'b1; + end + default :; + endcase + end // else: !if(Mode == 3 ) + end // case: 8'b00110010 + + +// 16 BIT LOAD GROUP + 8'b00000001,8'b00010001,8'b00100001,8'b00110001 : + begin + // LD dd,nn + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Read_To_Reg = 1'b1; + if (DPAIR == 2'b11 ) + begin + Set_BusA_To[3:0] = 4'b1000; + end + else + begin + Set_BusA_To[2:1] = DPAIR; + Set_BusA_To[0] = 1'b1; + end + end // case: 2 + + 3 : + begin + Inc_PC = 1'b1; + Read_To_Reg = 1'b1; + if (DPAIR == 2'b11 ) + begin + Set_BusA_To[3:0] = 4'b1001; + end + else + begin + Set_BusA_To[2:1] = DPAIR; + Set_BusA_To[0] = 1'b0; + end + end // case: 3 + + default :; + endcase // case(MCycle) + end // case: 8'b00000001,8'b00010001,8'b00100001,8'b00110001 + + 8'b00101010 : + begin + if (Mode == 3 ) + begin + // LDI A,(HL) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + Read_To_Acc = 1'b1; + IncDec_16 = 4'b0110; + end + + default :; + endcase + end + else + begin + // LD HL,(nn) + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + end + 4 : + begin + Set_BusA_To[2:0] = 3'b101; // L + Read_To_Reg = 1'b1; + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + end + 5 : + begin + Set_BusA_To[2:0] = 3'b100; // H + Read_To_Reg = 1'b1; + end + default :; + endcase + end // else: !if(Mode == 3 ) + end // case: 8'b00101010 + + 8'b00100010 : + begin + if (Mode == 3 ) + begin + // LDI (HL),A + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aXY; + Set_BusB_To = 4'b0111; + end + 2 : + begin + Write = 1'b1; + IncDec_16 = 4'b0110; + end + default :; + endcase + end + else + begin + // LD (nn),HL + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + Set_BusB_To = 4'b0101; // L + end + + 4 : + begin + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + Write = 1'b1; + Set_BusB_To = 4'b0100; // H + end + 5 : + Write = 1'b1; + default :; + endcase + end // else: !if(Mode == 3 ) + end // case: 8'b00100010 + + 8'b11111001 : + begin + // LD SP,HL + TStates = 3'b110; + LDSPHL = 1'b1; + end + + 8'b11000101,8'b11010101,8'b11100101,8'b11110101 : + begin + // PUSH qq + MCycles = 3'b011; + case (MCycle) + 1 : + begin + TStates = 3'b101; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + if (DPAIR == 2'b11 ) + begin + Set_BusB_To = 4'b0111; + end + else + begin + Set_BusB_To[2:1] = DPAIR; + Set_BusB_To[0] = 1'b0; + Set_BusB_To[3] = 1'b0; + end + end // case: 1 + + 2 : + begin + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + if (DPAIR == 2'b11 ) + begin + Set_BusB_To = 4'b1011; + end + else + begin + Set_BusB_To[2:1] = DPAIR; + Set_BusB_To[0] = 1'b1; + Set_BusB_To[3] = 1'b0; + end + Write = 1'b1; + end // case: 2 + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b11000101,8'b11010101,8'b11100101,8'b11110101 + + 8'b11000001,8'b11010001,8'b11100001,8'b11110001 : + begin + // POP qq + MCycles = 3'b011; + case (MCycle) + 1 : + Set_Addr_To = aSP; + 2 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + Read_To_Reg = 1'b1; + if (DPAIR == 2'b11 ) + begin + Set_BusA_To[3:0] = 4'b1011; + end + else + begin + Set_BusA_To[2:1] = DPAIR; + Set_BusA_To[0] = 1'b1; + end + end // case: 2 + + 3 : + begin + IncDec_16 = 4'b0111; + Read_To_Reg = 1'b1; + if (DPAIR == 2'b11 ) + begin + Set_BusA_To[3:0] = 4'b0111; + end + else + begin + Set_BusA_To[2:1] = DPAIR; + Set_BusA_To[0] = 1'b0; + end + end // case: 3 + + default :; + endcase // case(MCycle) + end // case: 8'b11000001,8'b11010001,8'b11100001,8'b11110001 + + +// EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + 8'b11101011 : + begin + if (Mode != 3 ) + begin + // EX DE,HL + ExchangeDH = 1'b1; + end + end + + 8'b00001000 : + begin + if (Mode == 3 ) + begin + // LD (nn),SP + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + Set_BusB_To = 4'b1000; + end + + 4 : + begin + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + Write = 1'b1; + Set_BusB_To = 4'b1001; + end + + 5 : + Write = 1'b1; + default :; + endcase + end + else if (Mode < 2 ) + begin + // EX AF,AF' + ExchangeAF = 1'b1; + end + end // case: 8'b00001000 + + 8'b11011001 : + begin + if (Mode == 3 ) + begin + // RETI + MCycles = 3'b011; + case (MCycle) + 1 : + Set_Addr_To = aSP; + 2 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + LDZ = 1'b1; + end + + 3 : + begin + Jump = 1'b1; + IncDec_16 = 4'b0111; + I_RETN = 1'b1; + SetEI = 1'b1; + end + default :; + endcase + end + else if (Mode < 2 ) + begin + // EXX + ExchangeRS = 1'b1; + end + end // case: 8'b11011001 + + 8'b11100011 : + begin + if (Mode != 3 ) + begin + // EX (SP),HL + MCycles = 3'b101; + case (MCycle) + 1 : + Set_Addr_To = aSP; + 2 : + begin + Read_To_Reg = 1'b1; + Set_BusA_To = 4'b0101; + Set_BusB_To = 4'b0101; + Set_Addr_To = aSP; + end + 3 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + TStates = 3'b100; + Write = 1'b1; + end + 4 : + begin + Read_To_Reg = 1'b1; + Set_BusA_To = 4'b0100; + Set_BusB_To = 4'b0100; + Set_Addr_To = aSP; + end + 5 : + begin + IncDec_16 = 4'b1111; + TStates = 3'b101; + Write = 1'b1; + end + + default :; + endcase + end // if (Mode != 3 ) + end // case: 8'b11100011 + + +// 8 BIT ARITHMETIC AND LOGICAL GROUP + 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111, + 8'b10001000,8'b10001001,8'b10001010,8'b10001011,8'b10001100,8'b10001101,8'b10001111, + 8'b10010000,8'b10010001,8'b10010010,8'b10010011,8'b10010100,8'b10010101,8'b10010111, + 8'b10011000,8'b10011001,8'b10011010,8'b10011011,8'b10011100,8'b10011101,8'b10011111, + 8'b10100000,8'b10100001,8'b10100010,8'b10100011,8'b10100100,8'b10100101,8'b10100111, + 8'b10101000,8'b10101001,8'b10101010,8'b10101011,8'b10101100,8'b10101101,8'b10101111, + 8'b10110000,8'b10110001,8'b10110010,8'b10110011,8'b10110100,8'b10110101,8'b10110111, + 8'b10111000,8'b10111001,8'b10111010,8'b10111011,8'b10111100,8'b10111101,8'b10111111 : + begin + // 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:0] = SSS; + Set_BusA_To[2:0] = 3'b111; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + end // case: 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111,... + + 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110 : + begin + // 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 = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusB_To[2:0] = SSS; + Set_BusA_To[2:0] = 3'b111; + end + + default :; + endcase // case(MCycle) + end // case: 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110 + + 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110 : + begin + // 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 = 3'b010; + if (MCycle == 3'b010 ) + begin + Inc_PC = 1'b1; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusB_To[2:0] = SSS; + Set_BusA_To[2:0] = 3'b111; + end + end // case: 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110 + + 8'b00000100,8'b00001100,8'b00010100,8'b00011100,8'b00100100,8'b00101100,8'b00111100 : + begin + // INC r + Set_BusB_To = 4'b1010; + Set_BusA_To[2:0] = DDD; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + PreserveC = 1'b1; + ALU_Op = 4'b0000; + end + + 8'b00110100 : + begin + // INC (HL) + MCycles = 3'b011; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + TStates = 3'b100; + Set_Addr_To = aXY; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + PreserveC = 1'b1; + ALU_Op = 4'b0000; + Set_BusB_To = 4'b1010; + Set_BusA_To[2:0] = DDD; + end // case: 2 + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00110100 + + 8'b00000101,8'b00001101,8'b00010101,8'b00011101,8'b00100101,8'b00101101,8'b00111101 : + begin + // DEC r + Set_BusB_To = 4'b1010; + Set_BusA_To[2:0] = DDD; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + PreserveC = 1'b1; + ALU_Op = 4'b0010; + end + + 8'b00110101 : + begin + // DEC (HL) + MCycles = 3'b011; + case (MCycle) + 1 : + Set_Addr_To = aXY; + 2 : + begin + TStates = 3'b100; + Set_Addr_To = aXY; + ALU_Op = 4'b0010; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + PreserveC = 1'b1; + Set_BusB_To = 4'b1010; + Set_BusA_To[2:0] = DDD; + end // case: 2 + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00110101 + +// GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + 8'b00100111 : + begin + // DAA + Set_BusA_To[2:0] = 3'b111; + Read_To_Reg = 1'b1; + ALU_Op = 4'b1100; + Save_ALU = 1'b1; + end + + 8'b00101111 : + // CPL + I_CPL = 1'b1; + + 8'b00111111 : + // CCF + I_CCF = 1'b1; + + 8'b00110111 : + // SCF + I_SCF = 1'b1; + + 8'b00000000 : + begin + if (NMICycle == 1'b1 ) + begin + // NMI + MCycles = 3'b011; + case (MCycle) + 1 : + begin + TStates = 3'b101; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1101; + end + + 2 : + begin + TStates = 3'b100; + Write = 1'b1; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1100; + end + + 3 : + begin + TStates = 3'b100; + Write = 1'b1; + end + + default :; + endcase // case(MCycle) + + end + else if (IntCycle == 1'b1 ) + begin + // INT (IM 2) + MCycles = 3'b101; + case (MCycle) + 1 : + begin + LDZ = 1'b1; + TStates = 3'b101; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1101; + end + + 2 : + begin + TStates = 3'b100; + Write = 1'b1; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1100; + end + + 3 : + begin + TStates = 3'b100; + Write = 1'b1; + end + + 4 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 5 : + Jump = 1'b1; + default :; + endcase + end + end // case: 8'b00000000 + + 8'b01110110 : + // HALT + Halt = 1'b1; + + 8'b11110011 : + // DI + SetDI = 1'b1; + + 8'b11111011 : + // EI + SetEI = 1'b1; + + // 16 BIT ARITHMETIC GROUP + 8'b00001001,8'b00011001,8'b00101001,8'b00111001 : + begin + // ADD HL,ss + MCycles = 3'b011; + case (MCycle) + 2 : + begin + NoRead = 1'b1; + ALU_Op = 4'b0000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusA_To[2:0] = 3'b101; + case (IR[5:4]) + 0,1,2 : + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b1; + end + + default : + Set_BusB_To = 4'b1000; + endcase // case(IR[5:4]) + + TStates = 3'b100; + Arith16 = 1'b1; + end // case: 2 + + 3 : + begin + NoRead = 1'b1; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0001; + Set_BusA_To[2:0] = 3'b100; + case (IR[5:4]) + 0,1,2 : + Set_BusB_To[2:1] = IR[5:4]; + default : + Set_BusB_To = 4'b1001; + endcase + Arith16 = 1'b1; + end // case: 3 + + default :; + endcase // case(MCycle) + end // case: 8'b00001001,8'b00011001,8'b00101001,8'b00111001 + + 8'b00000011,8'b00010011,8'b00100011,8'b00110011 : + begin + // INC ss + TStates = 3'b110; + IncDec_16[3:2] = 2'b01; + IncDec_16[1:0] = DPAIR; + end + + 8'b00001011,8'b00011011,8'b00101011,8'b00111011 : + begin + // DEC ss + TStates = 3'b110; + IncDec_16[3:2] = 2'b11; + IncDec_16[1:0] = DPAIR; + end + +// ROTATE AND SHIFT GROUP + 8'b00000111, + // RLCA + 8'b00010111, + // RLA + 8'b00001111, + // RRCA + 8'b00011111 : + // RRA + begin + Set_BusA_To[2:0] = 3'b111; + ALU_Op = 4'b1000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + end // case: 8'b00000111,... + + +// JUMP GROUP + 8'b11000011 : + begin + // JP nn + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Inc_PC = 1'b1; + Jump = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b11000011 + + 8'b11000010,8'b11001010,8'b11010010,8'b11011010,8'b11100010,8'b11101010,8'b11110010,8'b11111010 : + begin + if (IR[5] == 1'b1 && Mode == 3 ) + begin + case (IRB[4:3]) + 2'b00 : + begin + // LD ($FF00+C),A + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aBC; + Set_BusB_To = 4'b0111; + end + 2 : + begin + Write = 1'b1; + IORQ = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 2'b00 + + 2'b01 : + begin + // LD (nn),A + MCycles = 3'b100; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + Set_BusB_To = 4'b0111; + end + + 4 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: default :... + + 2'b10 : + begin + // LD A,($FF00+C) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aBC; + 2 : + begin + Read_To_Acc = 1'b1; + IORQ = 1'b1; + end + default :; + endcase // case(MCycle) + end // case: 2'b10 + + 2'b11 : + begin + // LD A,(nn) + MCycles = 3'b100; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + end + 4 : + Read_To_Acc = 1'b1; + default :; + endcase // case(MCycle) + end + endcase + end + else + begin + // JP cc,nn + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Inc_PC = 1'b1; + if (is_cc_true(F, IR[5:3]) ) + begin + Jump = 1'b1; + end + end + + default :; + endcase + end // else: !if(DPAIR == 2'b11 ) + end // case: 8'b11000010,8'b11001010,8'b11010010,8'b11011010,8'b11100010,8'b11101010,8'b11110010,8'b11111010 + + 8'b00011000 : + begin + if (Mode != 2 ) + begin + // JR e + MCycles = 3'b011; + case (MCycle) + 2 : + Inc_PC = 1'b1; + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + default :; + endcase + end // if (Mode != 2 ) + end // case: 8'b00011000 + + 8'b00111000 : + begin + if (Mode != 2 ) + begin + // JR C,e + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + if (F[Flag_C] == 1'b0 ) + begin + MCycles = 3'b010; + end + end + + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + default :; + endcase + end // if (Mode != 2 ) + end // case: 8'b00111000 + + 8'b00110000 : + begin + if (Mode != 2 ) + begin + // JR NC,e + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + if (F[Flag_C] == 1'b1 ) + begin + MCycles = 3'b010; + end + end + + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + default :; + endcase + end // if (Mode != 2 ) + end // case: 8'b00110000 + + 8'b00101000 : + begin + if (Mode != 2 ) + begin + // JR Z,e + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + if (F[Flag_Z] == 1'b0 ) + begin + MCycles = 3'b010; + end + end + + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + + default :; + endcase + end // if (Mode != 2 ) + end // case: 8'b00101000 + + 8'b00100000 : + begin + if (Mode != 2 ) + begin + // JR NZ,e + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + if (F[Flag_Z] == 1'b1 ) + begin + MCycles = 3'b010; + end + end + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + default :; + endcase + end // if (Mode != 2 ) + end // case: 8'b00100000 + + 8'b11101001 : + // JP (HL) + JumpXY = 1'b1; + + 8'b00010000 : + begin + if (Mode == 3 ) + begin + I_DJNZ = 1'b1; + end + else if (Mode < 2 ) + begin + // DJNZ,e + MCycles = 3'b011; + case (MCycle) + 1 : + begin + TStates = 3'b101; + I_DJNZ = 1'b1; + Set_BusB_To = 4'b1010; + Set_BusA_To[2:0] = 3'b000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0010; + end + 2 : + begin + I_DJNZ = 1'b1; + Inc_PC = 1'b1; + end + 3 : + begin + NoRead = 1'b1; + JumpE = 1'b1; + TStates = 3'b101; + end + default :; + endcase + end // if (Mode < 2 ) + end // case: 8'b00010000 + + +// CALL AND RETURN GROUP + 8'b11001101 : + begin + // CALL nn + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + IncDec_16 = 4'b1111; + Inc_PC = 1'b1; + TStates = 3'b100; + Set_Addr_To = aSP; + LDW = 1'b1; + Set_BusB_To = 4'b1101; + end + 4 : + begin + Write = 1'b1; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1100; + end + 5 : + begin + Write = 1'b1; + Call = 1'b1; + end + default :; + endcase // case(MCycle) + end // case: 8'b11001101 + + 8'b11000100,8'b11001100,8'b11010100,8'b11011100,8'b11100100,8'b11101100,8'b11110100,8'b11111100 : + begin + if (IR[5] == 1'b0 || Mode != 3 ) + begin + // CALL cc,nn + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + 3 : + begin + Inc_PC = 1'b1; + LDW = 1'b1; + if (is_cc_true(F, IR[5:3]) ) + begin + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + TStates = 3'b100; + Set_BusB_To = 4'b1101; + end + else + begin + MCycles = 3'b011; + end // else: !if(is_cc_true(F, IR[5:3]) ) + end // case: 3 + + 4 : + begin + Write = 1'b1; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1100; + end + + 5 : + begin + Write = 1'b1; + Call = 1'b1; + end + + default :; + endcase + end // if (IR[5] == 1'b0 || Mode != 3 ) + end // case: 8'b11000100,8'b11001100,8'b11010100,8'b11011100,8'b11100100,8'b11101100,8'b11110100,8'b11111100 + + 8'b11001001 : + begin + // RET + MCycles = 3'b011; + case (MCycle) + 1 : + begin + TStates = 3'b101; + Set_Addr_To = aSP; + end + + 2 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + LDZ = 1'b1; + end + + 3 : + begin + Jump = 1'b1; + IncDec_16 = 4'b0111; + end + + default :; + endcase // case(MCycle) + end // case: 8'b11001001 + + 8'b11000000,8'b11001000,8'b11010000,8'b11011000,8'b11100000,8'b11101000,8'b11110000,8'b11111000 : + begin + if (IR[5] == 1'b1 && Mode == 3 ) + begin + case (IRB[4:3]) + 2'b00 : + begin + // LD ($FF00+nn),A + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_Addr_To = aIOA; + Set_BusB_To = 4'b0111; + end + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 2'b00 + + 2'b01 : + begin + // ADD SP,n + MCycles = 3'b011; + case (MCycle) + 2 : + begin + ALU_Op = 4'b0000; + Inc_PC = 1'b1; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusA_To = 4'b1000; + Set_BusB_To = 4'b0110; + end + + 3 : + begin + NoRead = 1'b1; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0001; + Set_BusA_To = 4'b1001; + Set_BusB_To = 4'b1110; // Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + end + + default :; + endcase // case(MCycle) + end // case: 2'b01 + + 2'b10 : + begin + // LD A,($FF00+nn) + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_Addr_To = aIOA; + end + + 3 : + Read_To_Acc = 1'b1; + default :; + endcase // case(MCycle) + end // case: 2'b10 + + 2'b11 : + begin + // LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + end + + 4 : + begin + Set_BusA_To[2:0] = 3'b101; // L + Read_To_Reg = 1'b1; + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + end + + 5 : + begin + Set_BusA_To[2:0] = 3'b100; // H + Read_To_Reg = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 2'b11 + + endcase // case(IRB[4:3]) + + end + else + begin + // RET cc + MCycles = 3'b011; + case (MCycle) + 1 : + begin + if (is_cc_true(F, IR[5:3]) ) + begin + Set_Addr_To = aSP; + end + else + begin + MCycles = 3'b001; + end + TStates = 3'b101; + end // case: 1 + + 2 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + LDZ = 1'b1; + end + 3 : + begin + Jump = 1'b1; + IncDec_16 = 4'b0111; + end + default :; + endcase + end // else: !if(IR[5] == 1'b1 && Mode == 3 ) + end // case: 8'b11000000,8'b11001000,8'b11010000,8'b11011000,8'b11100000,8'b11101000,8'b11110000,8'b11111000 + + 8'b11000111,8'b11001111,8'b11010111,8'b11011111,8'b11100111,8'b11101111,8'b11110111,8'b11111111 : + begin + // RST p + MCycles = 3'b011; + case (MCycle) + 1 : + begin + TStates = 3'b101; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1101; + end + + 2 : + begin + Write = 1'b1; + IncDec_16 = 4'b1111; + Set_Addr_To = aSP; + Set_BusB_To = 4'b1100; + end + + 3 : + begin + Write = 1'b1; + RstP = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b11000111,8'b11001111,8'b11010111,8'b11011111,8'b11100111,8'b11101111,8'b11110111,8'b11111111 + +// INPUT AND OUTPUT GROUP + 8'b11011011 : + begin + if (Mode != 3 ) + begin + // IN A,(n) + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_Addr_To = aIOA; + end + + 3 : + begin + Read_To_Acc = 1'b1; + IORQ = 1'b1; + end + + default :; + endcase + end // if (Mode != 3 ) + end // case: 8'b11011011 + + 8'b11010011 : + begin + if (Mode != 3 ) + begin + // OUT (n),A + MCycles = 3'b011; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + Set_Addr_To = aIOA; + Set_BusB_To = 4'b0111; + end + + 3 : + begin + Write = 1'b1; + IORQ = 1'b1; + end + + default :; + endcase + end // if (Mode != 3 ) + end // case: 8'b11010011 + + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// MULTIBYTE INSTRUCTIONS +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + + 8'b11001011 : + begin + if (Mode != 2 ) + begin + Prefix = 2'b01; + end + end + + 8'b11101101 : + begin + if (Mode < 2 ) + begin + Prefix = 2'b10; + end + end + + 8'b11011101,8'b11111101 : + begin + if (Mode < 2 ) + begin + Prefix = 2'b11; + end + end + + endcase // case(IRB) + end // case: 2'b00 + + + 2'b01 : + begin + + + //---------------------------------------------------------------------------- + // + // CB prefixed instructions + // + //---------------------------------------------------------------------------- + + Set_BusA_To[2:0] = IR[2:0]; + Set_BusB_To[2:0] = IR[2:0]; + + case (IRB) + 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000111, + 8'b00010000,8'b00010001,8'b00010010,8'b00010011,8'b00010100,8'b00010101,8'b00010111, + 8'b00001000,8'b00001001,8'b00001010,8'b00001011,8'b00001100,8'b00001101,8'b00001111, + 8'b00011000,8'b00011001,8'b00011010,8'b00011011,8'b00011100,8'b00011101,8'b00011111, + 8'b00100000,8'b00100001,8'b00100010,8'b00100011,8'b00100100,8'b00100101,8'b00100111, + 8'b00101000,8'b00101001,8'b00101010,8'b00101011,8'b00101100,8'b00101101,8'b00101111, + 8'b00110000,8'b00110001,8'b00110010,8'b00110011,8'b00110100,8'b00110101,8'b00110111, + 8'b00111000,8'b00111001,8'b00111010,8'b00111011,8'b00111100,8'b00111101,8'b00111111 : + begin + // RLC r + // RL r + // RRC r + // RR r + // SLA r + // SRA r + // SRL r + // SLL r (Undocumented) / SWAP r + if (MCycle == 3'b001 ) begin + ALU_Op = 4'b1000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + end + end // case: 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000111,... + + 8'b00000110,8'b00010110,8'b00001110,8'b00011110,8'b00101110,8'b00111110,8'b00100110,8'b00110110 : + begin + // RLC (HL) + // RL (HL) + // RRC (HL) + // RR (HL) + // SRA (HL) + // SRL (HL) + // SLA (HL) + // SLL (HL) (Undocumented) / SWAP (HL) + MCycles = 3'b011; + case (MCycle) + 1 , 7 : + Set_Addr_To = aXY; + 2 : + begin + ALU_Op = 4'b1000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_Addr_To = aXY; + TStates = 3'b100; + end + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b00000110,8'b00010110,8'b00001110,8'b00011110,8'b00101110,8'b00111110,8'b00100110,8'b00110110 + + 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111, + 8'b01001000,8'b01001001,8'b01001010,8'b01001011,8'b01001100,8'b01001101,8'b01001111, + 8'b01010000,8'b01010001,8'b01010010,8'b01010011,8'b01010100,8'b01010101,8'b01010111, + 8'b01011000,8'b01011001,8'b01011010,8'b01011011,8'b01011100,8'b01011101,8'b01011111, + 8'b01100000,8'b01100001,8'b01100010,8'b01100011,8'b01100100,8'b01100101,8'b01100111, + 8'b01101000,8'b01101001,8'b01101010,8'b01101011,8'b01101100,8'b01101101,8'b01101111, + 8'b01110000,8'b01110001,8'b01110010,8'b01110011,8'b01110100,8'b01110101,8'b01110111, + 8'b01111000,8'b01111001,8'b01111010,8'b01111011,8'b01111100,8'b01111101,8'b01111111 : + begin + // BIT b,r + if (MCycle == 3'b001 ) + begin + Set_BusB_To[2:0] = IR[2:0]; + ALU_Op = 4'b1001; + end + end // case: 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111,... + + 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01110110,8'b01111110 : + begin + // BIT b,(HL) + MCycles = 3'b010; + case (MCycle) + 1 , 7 : + Set_Addr_To = aXY; + 2 : + begin + ALU_Op = 4'b1001; + TStates = 3'b100; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01110110,8'b01111110 + + 8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000111, + 8'b11001000,8'b11001001,8'b11001010,8'b11001011,8'b11001100,8'b11001101,8'b11001111, + 8'b11010000,8'b11010001,8'b11010010,8'b11010011,8'b11010100,8'b11010101,8'b11010111, + 8'b11011000,8'b11011001,8'b11011010,8'b11011011,8'b11011100,8'b11011101,8'b11011111, + 8'b11100000,8'b11100001,8'b11100010,8'b11100011,8'b11100100,8'b11100101,8'b11100111, + 8'b11101000,8'b11101001,8'b11101010,8'b11101011,8'b11101100,8'b11101101,8'b11101111, + 8'b11110000,8'b11110001,8'b11110010,8'b11110011,8'b11110100,8'b11110101,8'b11110111, + 8'b11111000,8'b11111001,8'b11111010,8'b11111011,8'b11111100,8'b11111101,8'b11111111 : + begin + // SET b,r + if (MCycle == 3'b001 ) + begin + ALU_Op = 4'b1010; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + end + end // case: 8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000111,... + + 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110 : + begin + // SET b,(HL) + MCycles = 3'b011; + case (MCycle) + 1 , 7 : + Set_Addr_To = aXY; + 2 : + begin + ALU_Op = 4'b1010; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_Addr_To = aXY; + TStates = 3'b100; + end + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110 + + 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111, + 8'b10001000,8'b10001001,8'b10001010,8'b10001011,8'b10001100,8'b10001101,8'b10001111, + 8'b10010000,8'b10010001,8'b10010010,8'b10010011,8'b10010100,8'b10010101,8'b10010111, + 8'b10011000,8'b10011001,8'b10011010,8'b10011011,8'b10011100,8'b10011101,8'b10011111, + 8'b10100000,8'b10100001,8'b10100010,8'b10100011,8'b10100100,8'b10100101,8'b10100111, + 8'b10101000,8'b10101001,8'b10101010,8'b10101011,8'b10101100,8'b10101101,8'b10101111, + 8'b10110000,8'b10110001,8'b10110010,8'b10110011,8'b10110100,8'b10110101,8'b10110111, + 8'b10111000,8'b10111001,8'b10111010,8'b10111011,8'b10111100,8'b10111101,8'b10111111 : + begin + // RES b,r + if (MCycle == 3'b001 ) + begin + ALU_Op = 4'b1011; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + end + end // case: 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111,... + + 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110 : + begin + // RES b,(HL) + MCycles = 3'b011; + case (MCycle) + 1 , 7 : + Set_Addr_To = aXY; + 2 : + begin + ALU_Op = 4'b1011; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_Addr_To = aXY; + TStates = 3'b100; + end + + 3 : + Write = 1'b1; + default :; + endcase // case(MCycle) + end // case: 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110 + + endcase // case(IRB) + end // case: 2'b01 + + + default : + begin : default_ed_block + + //---------------------------------------------------------------------------- + // + // ED prefixed instructions + // + //---------------------------------------------------------------------------- + + case (IRB) + 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000110,8'b00000111 + ,8'b00001000,8'b00001001,8'b00001010,8'b00001011,8'b00001100,8'b00001101,8'b00001110,8'b00001111 + ,8'b00010000,8'b00010001,8'b00010010,8'b00010011,8'b00010100,8'b00010101,8'b00010110,8'b00010111 + ,8'b00011000,8'b00011001,8'b00011010,8'b00011011,8'b00011100,8'b00011101,8'b00011110,8'b00011111 + ,8'b00100000,8'b00100001,8'b00100010,8'b00100011,8'b00100100,8'b00100101,8'b00100110,8'b00100111 + ,8'b00101000,8'b00101001,8'b00101010,8'b00101011,8'b00101100,8'b00101101,8'b00101110,8'b00101111 + ,8'b00110000,8'b00110001,8'b00110010,8'b00110011,8'b00110100,8'b00110101,8'b00110110,8'b00110111 + ,8'b00111000,8'b00111001,8'b00111010,8'b00111011,8'b00111100,8'b00111101,8'b00111110,8'b00111111 + + + ,8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000110,8'b10000111 + ,8'b10001000,8'b10001001,8'b10001010,8'b10001011,8'b10001100,8'b10001101,8'b10001110,8'b10001111 + ,8'b10010000,8'b10010001,8'b10010010,8'b10010011,8'b10010100,8'b10010101,8'b10010110,8'b10010111 + ,8'b10011000,8'b10011001,8'b10011010,8'b10011011,8'b10011100,8'b10011101,8'b10011110,8'b10011111 + , 8'b10100100,8'b10100101,8'b10100110,8'b10100111 + , 8'b10101100,8'b10101101,8'b10101110,8'b10101111 + , 8'b10110100,8'b10110101,8'b10110110,8'b10110111 + , 8'b10111100,8'b10111101,8'b10111110,8'b10111111 + ,8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000110,8'b11000111 + ,8'b11001000,8'b11001001,8'b11001010,8'b11001011,8'b11001100,8'b11001101,8'b11001110,8'b11001111 + ,8'b11010000,8'b11010001,8'b11010010,8'b11010011,8'b11010100,8'b11010101,8'b11010110,8'b11010111 + ,8'b11011000,8'b11011001,8'b11011010,8'b11011011,8'b11011100,8'b11011101,8'b11011110,8'b11011111 + ,8'b11100000,8'b11100001,8'b11100010,8'b11100011,8'b11100100,8'b11100101,8'b11100110,8'b11100111 + ,8'b11101000,8'b11101001,8'b11101010,8'b11101011,8'b11101100,8'b11101101,8'b11101110,8'b11101111 + ,8'b11110000,8'b11110001,8'b11110010,8'b11110011,8'b11110100,8'b11110101,8'b11110110,8'b11110111 + ,8'b11111000,8'b11111001,8'b11111010,8'b11111011,8'b11111100,8'b11111101,8'b11111110,8'b11111111 : + ; // NOP, undocumented + + 8'b01111110,8'b01111111 : + // NOP, undocumented + ; + // 8 BIT LOAD GROUP + 8'b01010111 : + begin + // LD A,I + Special_LD = 3'b100; + TStates = 3'b101; + end + + 8'b01011111 : + begin + // LD A,R + Special_LD = 3'b101; + TStates = 3'b101; + end + + 8'b01000111 : + begin + // LD I,A + Special_LD = 3'b110; + TStates = 3'b101; + end + + 8'b01001111 : + begin + // LD R,A + Special_LD = 3'b111; + TStates = 3'b101; + end + + // 16 BIT LOAD GROUP + 8'b01001011,8'b01011011,8'b01101011,8'b01111011 : + begin + // LD dd,(nn) + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + end + + 4 : + begin + Read_To_Reg = 1'b1; + if (IR[5:4] == 2'b11 ) + begin + Set_BusA_To = 4'b1000; + end + else + begin + Set_BusA_To[2:1] = IR[5:4]; + Set_BusA_To[0] = 1'b1; + end + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + end // case: 4 + + 5 : + begin + Read_To_Reg = 1'b1; + if (IR[5:4] == 2'b11 ) + begin + Set_BusA_To = 4'b1001; + end + else + begin + Set_BusA_To[2:1] = IR[5:4]; + Set_BusA_To[0] = 1'b0; + end + end // case: 5 + + default :; + endcase // case(MCycle) + end // case: 8'b01001011,8'b01011011,8'b01101011,8'b01111011 + + + 8'b01000011,8'b01010011,8'b01100011,8'b01110011 : + begin + // LD (nn),dd + MCycles = 3'b101; + case (MCycle) + 2 : + begin + Inc_PC = 1'b1; + LDZ = 1'b1; + end + + 3 : + begin + Set_Addr_To = aZI; + Inc_PC = 1'b1; + LDW = 1'b1; + if (IR[5:4] == 2'b11 ) + begin + Set_BusB_To = 4'b1000; + end + else + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b1; + Set_BusB_To[3] = 1'b0; + end + end // case: 3 + + 4 : + begin + Inc_WZ = 1'b1; + Set_Addr_To = aZI; + Write = 1'b1; + if (IR[5:4] == 2'b11 ) + begin + Set_BusB_To = 4'b1001; + end + else + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b0; + Set_BusB_To[3] = 1'b0; + end + end // case: 4 + + 5 : + begin + Write = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01000011,8'b01010011,8'b01100011,8'b01110011 + + 8'b10100000 , 8'b10101000 , 8'b10110000 , 8'b10111000 : + begin + // LDI, LDD, LDIR, LDDR + MCycles = 3'b100; + case (MCycle) + 1 : + begin + Set_Addr_To = aXY; + IncDec_16 = 4'b1100; // BC + end + + 2 : + begin + Set_BusB_To = 4'b0110; + Set_BusA_To[2:0] = 3'b111; + ALU_Op = 4'b0000; + Set_Addr_To = aDE; + if (IR[3] == 1'b0 ) + begin + IncDec_16 = 4'b0110; // IX + end + else + begin + IncDec_16 = 4'b1110; + end + end // case: 2 + + 3 : + begin + I_BT = 1'b1; + TStates = 3'b101; + Write = 1'b1; + if (IR[3] == 1'b0 ) + begin + IncDec_16 = 4'b0101; // DE + end + else + begin + IncDec_16 = 4'b1101; + end + end // case: 3 + + 4 : + begin + NoRead = 1'b1; + TStates = 3'b101; + end + + default :; + endcase // case(MCycle) + end // case: 8'b10100000 , 8'b10101000 , 8'b10110000 , 8'b10111000 + + 8'b10100001 , 8'b10101001 , 8'b10110001 , 8'b10111001 : + begin + // CPI, CPD, CPIR, CPDR + MCycles = 3'b100; + case (MCycle) + 1 : + begin + Set_Addr_To = aXY; + IncDec_16 = 4'b1100; // BC + end + + 2 : + begin + Set_BusB_To = 4'b0110; + Set_BusA_To[2:0] = 3'b111; + ALU_Op = 4'b0111; + Save_ALU = 1'b1; + PreserveC = 1'b1; + if (IR[3] == 1'b0 ) + begin + IncDec_16 = 4'b0110; + end + else + begin + IncDec_16 = 4'b1110; + end + end // case: 2 + + 3 : + begin + NoRead = 1'b1; + I_BC = 1'b1; + TStates = 3'b101; + end + + 4 : + begin + NoRead = 1'b1; + TStates = 3'b101; + end + + default :; + endcase // case(MCycle) + end // case: 8'b10100001 , 8'b10101001 , 8'b10110001 , 8'b10111001 + + 8'b01000100,8'b01001100,8'b01010100,8'b01011100,8'b01100100,8'b01101100,8'b01110100,8'b01111100 : + begin + // NEG + ALU_Op = 4'b0010; + Set_BusB_To = 4'b0111; + Set_BusA_To = 4'b1010; + Read_To_Acc = 1'b1; + Save_ALU = 1'b1; + end + + 8'b01000110,8'b01001110,8'b01100110,8'b01101110 : + begin + // IM 0 + IMode = 2'b00; + end + + 8'b01010110,8'b01110110 : + // IM 1 + IMode = 2'b01; + + 8'b01011110,8'b01110111 : + // IM 2 + IMode = 2'b10; + + // 16 bit arithmetic + 8'b01001010,8'b01011010,8'b01101010,8'b01111010 : + begin + // ADC HL,ss + MCycles = 3'b011; + case (MCycle) + 2 : + begin + NoRead = 1'b1; + ALU_Op = 4'b0001; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusA_To[2:0] = 3'b101; + case (IR[5:4]) + 0,1,2 : + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b1; + end + default : + Set_BusB_To = 4'b1000; + endcase + TStates = 3'b100; + end // case: 2 + + 3 : + begin + NoRead = 1'b1; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0001; + Set_BusA_To[2:0] = 3'b100; + case (IR[5:4]) + 0,1,2 : + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b0; + end + default : + Set_BusB_To = 4'b1001; + endcase // case(IR[5:4]) + end // case: 3 + + default :; + endcase // case(MCycle) + end // case: 8'b01001010,8'b01011010,8'b01101010,8'b01111010 + + 8'b01000010,8'b01010010,8'b01100010,8'b01110010 : + begin + // SBC HL,ss + MCycles = 3'b011; + case (MCycle) + 2 : + begin + NoRead = 1'b1; + ALU_Op = 4'b0011; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusA_To[2:0] = 3'b101; + case (IR[5:4]) + 0,1,2 : + begin + Set_BusB_To[2:1] = IR[5:4]; + Set_BusB_To[0] = 1'b1; + end + default : + Set_BusB_To = 4'b1000; + endcase + TStates = 3'b100; + end // case: 2 + + 3 : + begin + NoRead = 1'b1; + ALU_Op = 4'b0011; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + Set_BusA_To[2:0] = 3'b100; + case (IR[5:4]) + 0,1,2 : + Set_BusB_To[2:1] = IR[5:4]; + default : + Set_BusB_To = 4'b1001; + endcase + end // case: 3 + + default :; + + endcase // case(MCycle) + end // case: 8'b01000010,8'b01010010,8'b01100010,8'b01110010 + + 8'b01101111 : + begin + // RLD + MCycles = 3'b100; + case (MCycle) + 2 : + begin + NoRead = 1'b1; + Set_Addr_To = aXY; + end + + 3 : + begin + Read_To_Reg = 1'b1; + Set_BusB_To[2:0] = 3'b110; + Set_BusA_To[2:0] = 3'b111; + ALU_Op = 4'b1101; + TStates = 3'b100; + Set_Addr_To = aXY; + Save_ALU = 1'b1; + end + + 4 : + begin + I_RLD = 1'b1; + Write = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01101111 + + 8'b01100111 : + begin + // RRD + MCycles = 3'b100; + case (MCycle) + 2 : + Set_Addr_To = aXY; + 3 : + begin + Read_To_Reg = 1'b1; + Set_BusB_To[2:0] = 3'b110; + Set_BusA_To[2:0] = 3'b111; + ALU_Op = 4'b1110; + TStates = 3'b100; + Set_Addr_To = aXY; + Save_ALU = 1'b1; + end + + 4 : + begin + I_RRD = 1'b1; + Write = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01100111 + + 8'b01000101,8'b01001101,8'b01010101,8'b01011101,8'b01100101,8'b01101101,8'b01110101,8'b01111101 : + begin + // RETI, RETN + MCycles = 3'b011; + case (MCycle) + 1 : + Set_Addr_To = aSP; + + 2 : + begin + IncDec_16 = 4'b0111; + Set_Addr_To = aSP; + LDZ = 1'b1; + end + + 3 : + begin + Jump = 1'b1; + IncDec_16 = 4'b0111; + I_RETN = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01000101,8'b01001101,8'b01010101,8'b01011101,8'b01100101,8'b01101101,8'b01110101,8'b01111101 + + 8'b01000000,8'b01001000,8'b01010000,8'b01011000,8'b01100000,8'b01101000,8'b01110000,8'b01111000 : + begin + // IN r,(C) + MCycles = 3'b010; + case (MCycle) + 1 : + Set_Addr_To = aBC; + + 2 : + begin + IORQ = 1'b1; + if (IR[5:3] != 3'b110 ) + begin + Read_To_Reg = 1'b1; + Set_BusA_To[2:0] = IR[5:3]; + end + I_INRC = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01000000,8'b01001000,8'b01010000,8'b01011000,8'b01100000,8'b01101000,8'b01110000,8'b01111000 + + 8'b01000001,8'b01001001,8'b01010001,8'b01011001,8'b01100001,8'b01101001,8'b01110001,8'b01111001 : + begin + // OUT (C),r + // OUT (C),0 + MCycles = 3'b010; + case (MCycle) + 1 : + begin + Set_Addr_To = aBC; + Set_BusB_To[2:0] = IR[5:3]; + if (IR[5:3] == 3'b110 ) + begin + Set_BusB_To[3] = 1'b1; + end + end + + 2 : + begin + Write = 1'b1; + IORQ = 1'b1; + end + + default :; + endcase // case(MCycle) + end // case: 8'b01000001,8'b01001001,8'b01010001,8'b01011001,8'b01100001,8'b01101001,8'b01110001,8'b01111001 + + 8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010 : + begin + // INI, IND, INIR, INDR + MCycles = 3'b100; + case (MCycle) + 1 : + begin + Set_Addr_To = aBC; + Set_BusB_To = 4'b1010; + Set_BusA_To = 4'b0000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0010; + end + + 2 : + begin + IORQ = 1'b1; + Set_BusB_To = 4'b0110; + Set_Addr_To = aXY; + end + + 3 : + begin + if (IR[3] == 1'b0 ) + begin + IncDec_16 = 4'b0010; + end + else + begin + IncDec_16 = 4'b1010; + end + TStates = 3'b100; + Write = 1'b1; + I_BTR = 1'b1; + end // case: 3 + + 4 : + begin + NoRead = 1'b1; + TStates = 3'b101; + end + + default :; + endcase // case(MCycle) + end // case: 8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010 + + 8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011 : + begin + // OUTI, OUTD, OTIR, OTDR + MCycles = 3'b100; + case (MCycle) + 1 : + begin + TStates = 3'b101; + Set_Addr_To = aXY; + Set_BusB_To = 4'b1010; + Set_BusA_To = 4'b0000; + Read_To_Reg = 1'b1; + Save_ALU = 1'b1; + ALU_Op = 4'b0010; + end + + 2 : + begin + Set_BusB_To = 4'b0110; + Set_Addr_To = aBC; + end + + 3 : + begin + if (IR[3] == 1'b0 ) + begin + IncDec_16 = 4'b0010; + end + else + begin + IncDec_16 = 4'b1010; + end + IORQ = 1'b1; + Write = 1'b1; + I_BTR = 1'b1; + end // case: 3 + + 4 : + begin + NoRead = 1'b1; + TStates = 3'b101; + end + + default :; + endcase // case(MCycle) + end // case: 8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011 + + endcase // case(IRB) + end // block: default_ed_block + endcase // case(ISet) + + if (Mode == 1 ) + begin + if (MCycle == 3'b001 ) + begin + //TStates = 3'b100; + end + else + begin + TStates = 3'b011; + end + end + + if (Mode == 3 ) + begin + if (MCycle == 3'b001 ) + begin + //TStates = 3'b100; + end + else + begin + TStates = 3'b100; + end + end + + if (Mode < 2 ) + begin + if (MCycle == 3'b110 ) + begin + Inc_PC = 1'b1; + if (Mode == 1 ) + begin + Set_Addr_To = aXY; + TStates = 3'b100; + Set_BusB_To[2:0] = SSS; + Set_BusB_To[3] = 1'b0; + end + if (IRB == 8'b00110110 || IRB == 8'b11001011 ) + begin + Set_Addr_To = aNone; + end + end + if (MCycle == 3'b111 ) + begin + if (Mode == 0 ) + begin + TStates = 3'b101; + end + if (ISet != 2'b01 ) + begin + Set_Addr_To = aXY; + end + Set_BusB_To[2:0] = SSS; + Set_BusB_To[3] = 1'b0; + if (IRB == 8'b00110110 || ISet == 2'b01 ) + begin + // LD (HL),n + Inc_PC = 1'b1; + end + else + begin + NoRead = 1'b1; + end + end + end // if (Mode < 2 ) + + end // always @ (IR, ISet, MCycle, F, NMICycle, IntCycle) + +// synopsys dc_script_begin +// set_attribute current_design "revision" "$Id: tv80_mcode.v,v 1.1 2004/05/16 17:39:57 ghutchis Exp $" -type string -quiet +// synopsys dc_script_end +endmodule // T80_MCode + + + diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v new file mode 100644 index 000000000..8218407b6 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v @@ -0,0 +1,71 @@ +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80_reg (/*AUTOARG*/ + // Outputs + DOBH, DOAL, DOCL, DOBL, DOCH, DOAH, + // Inputs + AddrC, AddrA, AddrB, DIH, DIL, clk, CEN, WEH, WEL + ); + input [2:0] AddrC; + output [7:0] DOBH; + input [2:0] AddrA; + input [2:0] AddrB; + input [7:0] DIH; + output [7:0] DOAL; + output [7:0] DOCL; + input [7:0] DIL; + output [7:0] DOBL; + output [7:0] DOCH; + output [7:0] DOAH; + input clk, CEN, WEH, WEL; + + reg [7:0] RegsH [0:7]; + reg [7:0] RegsL [0:7]; + + always @(posedge clk) + begin + if (CEN) + begin + if (WEH) RegsH[AddrA] <= DIH; + if (WEL) RegsL[AddrA] <= DIL; + end + end + + assign DOAH = RegsH[AddrA]; + assign DOAL = RegsL[AddrA]; + assign DOBH = RegsH[AddrB]; + assign DOBL = RegsL[AddrB]; + assign DOCH = RegsH[AddrC]; + assign DOCL = RegsL[AddrC]; + + // break out ram bits for waveform debug + wire [7:0] H = RegsH[2]; + wire [7:0] L = RegsL[2]; + +// synopsys dc_script_begin +// set_attribute current_design "revision" "$Id: tv80_reg.v,v 1.1 2004/05/16 17:39:57 ghutchis Exp $" -type string -quiet +// synopsys dc_script_end +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v b/openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v new file mode 100644 index 000000000..e8b8085c3 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v @@ -0,0 +1,160 @@ +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80s (/*AUTOARG*/ + // Outputs + m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, do, + // Inputs + reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di + ); + + parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + parameter T2Write = 0; // 0 => wr_n active in T3, /=0 => wr_n active in T2 + parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle + + + input reset_n; + input clk; + input wait_n; + input int_n; + input nmi_n; + input busrq_n; + output m1_n; + output mreq_n; + output iorq_n; + output rd_n; + output wr_n; + output rfsh_n; + output halt_n; + output busak_n; + output [15:0] A; + input [7:0] di; + output [7:0] do; + + reg mreq_n; + reg iorq_n; + reg rd_n; + reg wr_n; + + wire cen; + wire intcycle_n; + wire no_read; + wire write; + wire iorq; + reg [7:0] di_reg; + wire [2:0] mcycle; + wire [2:0] tstate; + + assign cen = 1; + + tv80_core i_tv80_core + ( + .cen (cen), + .m1_n (m1_n), + .iorq (iorq), + .no_read (no_read), + .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 (clk), + .IntE (), + .stop (), + .A (A), + .dinst (di), + .di (di_reg), + .do (do), + .mc (mcycle), + .ts (tstate), + .intcycle_n (intcycle_n) + ); + + always @(posedge clk) + begin + if (!reset_n) + begin + rd_n <= #1 1'b1; + wr_n <= #1 1'b1; + iorq_n <= #1 1'b1; + mreq_n <= #1 1'b1; + di_reg <= #1 0; + end + else + begin + rd_n <= #1 1'b1; + wr_n <= #1 1'b1; + iorq_n <= #1 1'b1; + mreq_n <= #1 1'b1; + if (mcycle == 3'b001) + begin + if (tstate == 3'b001 || (tstate == 3'b010 && wait_n == 1'b0)) + begin + rd_n <= #1 ~ intcycle_n; + mreq_n <= #1 ~ intcycle_n; + iorq_n <= #1 intcycle_n; + end + if (tstate == 3'b011) + mreq_n <= #1 1'b0; + end // if (mcycle == 3'b001) + else + begin + if ((tstate == 3'b001 || (tstate == 3'b010 && wait_n == 1'b0)) && no_read == 1'b0 && write == 1'b0) + begin + rd_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + if (T2Write == 0) + begin + if (tstate == 3'b010 && write == 1'b1) + begin + wr_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + end + else + begin + if ((tstate == 3'b001 || (tstate == 3'b010 && wait_n == 1'b0)) && write == 1'b1) + begin + wr_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + end // else: !if(T2write == 0) + + end // else: !if(mcycle == 3'b001) + + if (tstate == 3'b010 && wait_n == 1'b1) + di_reg <= #1 di; + end // else: !if(!reset_n) + end // always @ (posedge clk or negedge reset_n) + +endmodule // t80s + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v new file mode 100644 index 000000000..f4c935b89 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v @@ -0,0 +1,115 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB CRC5 and CRC16 Modules //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_crc16.v,v 1.2 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_crc16.v,v $ +// Revision 1.2 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:42 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +/////////////////////////////////////////////////////////////////// +// +// CRC16 +// +/////////////////////////////////////////////////////////////////// + +module usbf_crc16(crc_in, din, crc_out); +input [15:0] crc_in; +input [7:0] din; +output [15:0] crc_out; + +assign crc_out[0] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ + din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^ + crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ + crc_in[14] ^ crc_in[15]; +assign crc_out[1] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ + din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^ + crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15]; +assign crc_out[2] = din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9]; +assign crc_out[3] = din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10]; +assign crc_out[4] = din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11]; +assign crc_out[5] = din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12]; +assign crc_out[6] = din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13]; +assign crc_out[7] = din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14]; +assign crc_out[8] = din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15]; +assign crc_out[9] = din[7] ^ crc_in[1] ^ crc_in[15]; +assign crc_out[10] = crc_in[2]; +assign crc_out[11] = crc_in[3]; +assign crc_out[12] = crc_in[4]; +assign crc_out[13] = crc_in[5]; +assign crc_out[14] = crc_in[6]; +assign crc_out[15] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ + din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^ + crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ + crc_in[14] ^ crc_in[15]; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v new file mode 100644 index 000000000..d382d8812 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB CRC5 and CRC16 Modules //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_crc5.v,v 1.2 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_crc5.v,v $ +// Revision 1.2 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:42 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +/////////////////////////////////////////////////////////////////// +// +// CRC5 +// +/////////////////////////////////////////////////////////////////// + +module usbf_crc5(crc_in, din, crc_out); +input [4:0] crc_in; +input [10:0] din; +output [4:0] crc_out; + +assign crc_out[0] = din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^ + din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[1] = din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^ + crc_in[0] ^ crc_in[1] ^ crc_in[4]; + +assign crc_out[2] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^ + din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^ + crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[3] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^ + din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[4] = din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^ + crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v new file mode 100644 index 000000000..4c8f8ffac --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v @@ -0,0 +1,294 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB function defines file //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_defines.v,v 1.6 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_defines.v,v $ +// Revision 1.6 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.5 2001/11/04 12:22:43 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.4 2001/09/23 08:39:33 rudi +// +// Renamed DEBUG and VERBOSE_DEBUG to USBF_DEBUG and USBF_VERBOSE_DEBUG ... +// +// Revision 1.3 2001/09/13 13:14:02 rudi +// +// Fixed a problem that would sometimes prevent the core to come out of +// reset and immediately be operational ... +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:52 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.2 2001/03/07 09:08:13 rudi +// +// Added USB control signaling (Line Status) block. Fixed some minor +// typos, added resume bit and signal. +// +// Revision 0.1.0.1 2001/02/28 08:11:35 rudi +// Initial Release +// +// + +`timescale 1ns / 10ps + +// Uncomment the lines below to get various levels of debugging +// verbosity ... +`define USBF_DEBUG +//`define USBF_VERBOSE_DEBUG + +// Uncomment the line below to run the test bench +// Comment it out to use your own address parameters ... +`define USBF_TEST_IMPL + +// For each endpoint that should actually be instantiated, +// set the below define value to a one. Uncomment the define +// statement for unused endpoints. The endpoints should be +// sequential, e.q. 1,2,3. I have not tested what happens if +// you select endpoints in a non sequential manner e.g. 1,4,6 +// Actual (logical) endpoint IDs are set by the software. There +// is no correlation between the physical endpoint number (below) +// and the actual (logical) endpoint number. +`ifdef USBF_TEST_IMPL + // Do not modify this section + // this is to run the test bench + `define USBF_HAVE_EP1 1 + `define USBF_HAVE_EP2 1 + `define USBF_HAVE_EP3 1 +`else + // Modify this section to suit your implementation + `define USBF_HAVE_EP1 1 + `define USBF_HAVE_EP2 1 + `define USBF_HAVE_EP3 1 + //`define USBF_HAVE_EP4 1 + //`define USBF_HAVE_EP5 1 + //`define USBF_HAVE_EP6 1 + //`define USBF_HAVE_EP7 1 + //`define USBF_HAVE_EP8 1 + //`define USBF_HAVE_EP9 1 + //`define USBF_HAVE_EP10 1 + //`define USBF_HAVE_EP11 1 + //`define USBF_HAVE_EP12 1 + //`define USBF_HAVE_EP13 1 + //`define USBF_HAVE_EP14 1 + //`define USBF_HAVE_EP15 1 +`endif + + +// Highest address line number that goes to the USB core +// Typically only A0 through A17 are needed, where A17 +// selects between the internal buffer memory and the +// register file. +// Implementations may choose to have a more complex address +// decoding .... + +`ifdef USBF_TEST_IMPL + // Do not modify this section + // this is to run the test bench + `define USBF_UFC_HADR 17 + `define USBF_RF_SEL (!wb_addr_i[17]) + `define USBF_MEM_SEL (wb_addr_i[17]) + `define USBF_SSRAM_HADR 14 + //`define USBF_ASYNC_RESET + +`else + // Modify this section to suit your implementation + `define USBF_UFC_HADR 12 + // Address Decoding for Register File select + `define USBF_RF_SEL (!wb_addr_i[12]) + // Address Decoding for Buffer Memory select + `define USBF_MEM_SEL (wb_addr_i[12]) + `define USBF_SSRAM_HADR 9 + // The next statement determines if reset is async or sync. + // If the define is uncommented the reset will be ASYNC. + //`define USBF_ASYNC_RESET +`endif + + +///////////////////////////////////////////////////////////////////// +// +// Items below this point should NOT be modified by the end user +// UNLESS you know exactly what you are doing ! +// Modify at you own risk !!! +// +///////////////////////////////////////////////////////////////////// + +// PID Encodings +`define USBF_T_PID_OUT 4'b0001 +`define USBF_T_PID_IN 4'b1001 +`define USBF_T_PID_SOF 4'b0101 +`define USBF_T_PID_SETUP 4'b1101 +`define USBF_T_PID_DATA0 4'b0011 +`define USBF_T_PID_DATA1 4'b1011 +`define USBF_T_PID_DATA2 4'b0111 +`define USBF_T_PID_MDATA 4'b1111 +`define USBF_T_PID_ACK 4'b0010 +`define USBF_T_PID_NACK 4'b1010 +`define USBF_T_PID_STALL 4'b1110 +`define USBF_T_PID_NYET 4'b0110 +`define USBF_T_PID_PRE 4'b1100 +`define USBF_T_PID_ERR 4'b1100 +`define USBF_T_PID_SPLIT 4'b1000 +`define USBF_T_PID_PING 4'b0100 +`define USBF_T_PID_RES 4'b0000 + +// The HMS_DEL is a constant for the "Half Micro Second" +// Clock pulse generator. This constant specifies how many +// Phy clocks there are between two hms_clock pulses. This +// constant plus 2 represents the actual delay. +// Example: For a 60 Mhz (16.667 nS period) Phy Clock, the +// delay must be 30 phy clocks: 500ns / 16.667nS = 30 clocks +`define USBF_HMS_DEL 5'h1c + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has 622nS in Full Speed +// mode and 400nS in High Speed mode to reply. RX_ACK_TO_VAL_FS +// and RX_ACK_TO_VAL_HS are the numbers of UTMI clock cycles +// minus 2 for Full and High Speed modes. +`define USBF_RX_ACK_TO_VAL_FS 8'd36 +`define USBF_RX_ACK_TO_VAL_HS 8'd22 + + +// After sending an OUT token the host must send a data packet. +// The host has 622nS in Full Speed mode and 400nS in High Speed +// mode to send the data packet. +// TX_DATA_TO_VAL_FS and TX_DATA_TO_VAL_HS are is the numbers of +// UTMI clock cycles minus 2. +`define USBF_TX_DATA_TO_VAL_FS 8'd36 +`define USBF_TX_DATA_TO_VAL_HS 8'd22 + + +// -------------------------------------------------- +// USB Line state & Speed Negotiation Time Values + + +// Prescaler Clear value. +// The prescaler generates a 0.25uS pulse, from a nominal PHY clock of +// 60 Mhz. 250nS/16.667ns=15. The prescaler has to be cleared every 15 +// cycles. Due to the pipeline, subtract 2 from 15, resulting in 13 cycles. +// !!! This is the only place that needs to be changed if a PHY with different +// !!! clock output is used. +`define USBF_T1_PS_250_NS 4'd13 + +// uS counter representation of 2.5uS (2.5/0.25=10) +`define USBF_T1_C_2_5_US 8'd10 + +// uS counter clear value +// The uS counter counts the time in 0.25uS intervals. It also generates +// a count enable to the mS counter, every 62.5 uS. +// The clear value is 62.5uS/0.25uS=250 cycles. +`define USBF_T1_C_62_5_US 8'd250 + +// mS counter representation of 3.0mS (3.0/0.0625=48) +`define USBF_T1_C_3_0_MS 8'd48 + +// mS counter representation of 3.125mS (3.125/0.0625=50) +`define USBF_T1_C_3_125_MS 8'd50 + +// mS counter representation of 5mS (5/0.0625=80) +`define USBF_T1_C_5_MS 8'd80 + +// Multi purpose Counter Prescaler, generate 2.5 uS period +// 2500/16.667ns=150 (minus 2 for pipeline) +`define USBF_T2_C_2_5_US 8'd148 + +// Generate 0.5mS period from the 2.5 uS clock +// 500/2.5 = 200 +`define USBF_T2_C_0_5_MS 8'd200 + +// Indicate when internal wakeup has completed +// me_cnt counts 0.5 mS intervals. E.g.: 5.0mS are (5/0.5) 10 ticks +// Must be 0 =< 10 mS +`define USBF_T2_C_WAKEUP 8'd10 + +// Indicate when 100uS have passed +// me_ps2 counts 2.5uS intervals. 100uS are (100/2.5) 40 ticks +`define USBF_T2_C_100_US 8'd40 + +// Indicate when 1.0 mS have passed +// me_cnt counts 0.5 mS intervals. 1.0mS are (1/0.5) 2 ticks +`define USBF_T2_C_1_0_MS 8'd2 + +// Indicate when 1.2 mS have passed +// me_cnt counts 0.5 mS intervals. 1.2mS are (1.2/0.5) 2 ticks +`define USBF_T2_C_1_2_MS 8'd2 + +// Indicate when 100 mS have passed +// me_cnt counts 0.5 mS intervals. 100mS are (100/0.5) 200 ticks +`define USBF_T2_C_100_MS 8'd200 + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v new file mode 100644 index 000000000..2cb16d575 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v @@ -0,0 +1,516 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Endpoint register File //// +//// This module contains all registers for ONE endpoint //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_ep_rf.v,v 1.4 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_ep_rf.v,v $ +// Revision 1.4 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.3 2001/11/04 12:22:44 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.2 2001/11/03 03:26:22 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:51 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:44 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +// Endpoint register File +module usbf_ep_rf(clk, wclk, rst, + + // Wishbone Interface + adr, re, we, din, dout, inta, intb, + dma_req, dma_ack, + + // Internal Interface + + idin, + ep_sel, ep_match, + buf0_rl, buf0_set, buf1_set, + uc_bsel_set, uc_dpd_set, + + int_buf1_set, int_buf0_set, int_upid_set, + int_crc16_set, int_to_set, int_seqerr_set, + out_to_small, + + csr, buf0, buf1, dma_in_buf_sz1, dma_out_buf_avail + ); + +input clk, wclk, rst; +input [1:0] adr; +input re; +input we; +input [31:0] din; +output [31:0] dout; +output inta, intb; +output dma_req; +input dma_ack; + +input [31:0] idin; // Data Input +input [3:0] ep_sel; // Endpoint Number Input +output ep_match; // Asserted to indicate a ep no is matched +input buf0_rl; // Reload Buf 0 with original values + +input buf0_set; // Write to buf 0 +input buf1_set; // Write to buf 1 +input uc_bsel_set; // Write to the uc_bsel field +input uc_dpd_set; // Write to the uc_dpd field +input int_buf1_set; // Set buf1 full/empty interrupt +input int_buf0_set; // Set buf0 full/empty interrupt +input int_upid_set; // Set unsupported PID interrupt +input int_crc16_set; // Set CRC16 error interrupt +input int_to_set; // Set time out interrupt +input int_seqerr_set; // Set PID sequence error interrupt +input out_to_small; // OUT packet was to small for DMA operation + +output [31:0] csr; // Internal CSR Output +output [31:0] buf0; // Internal Buf 0 Output +output [31:0] buf1; // Internal Buf 1 Output +output dma_in_buf_sz1; // Indicates that the DMA IN buffer has 1 max_pl_sz + // packet available +output dma_out_buf_avail;// Indicates that there is space for at least + // one MAX_PL_SZ packet in the buffer + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [31:0] dout; + +// CSR +reg [12:0] csr0; +reg ots_stop; +reg [12:0] csr1; +reg [1:0] uc_bsel, uc_dpd; + +reg [5:0] iena, ienb; // Interrupt enables +reg [6:0] int_stat; // Interrupt status + +wire we0, we1, we2, we3; +reg [31:0] buf0; +reg [31:0] buf1; +reg [31:0] buf0_orig; + +reg inta, intb; + +// DMA Logic Registers +reg [11:0] dma_out_cnt; +wire dma_out_cnt_is_zero; +reg dma_out_buf_avail; +reg [11:0] dma_out_left; + +reg [11:0] dma_in_cnt; +reg dma_in_buf_sz1; + +reg dma_req_r; +wire dma_req_d; +wire dma_req_in_d; +wire dma_req_out_d; +reg r1, r2, r4, r5; +wire dma_ack_i; +reg dma_req_out_hold, dma_req_in_hold ; +reg [11:0] buf0_orig_m3; +wire dma_req_hold; +reg set_r; +reg ep_match_r; +reg int_re; + +// Aliases +wire [31:0] csr; +wire [31:0] int; +wire dma_en; +wire [10:0] max_pl_sz; +wire ep_in; +wire ep_out; + +assign csr = {uc_bsel, uc_dpd, csr1, 1'h0, ots_stop, csr0}; +assign int = {2'h0, iena, 2'h0,ienb, 9'h0, int_stat}; +assign dma_en = csr[15]; +assign max_pl_sz = csr[10:0]; +assign ep_in = csr[27:26]==2'b01; +assign ep_out = csr[27:26]==2'b10; + +/////////////////////////////////////////////////////////////////// +// +// WISHBONE Access +// + +always @(adr or csr or int or buf0 or buf1) + case(adr) // synopsys full_case parallel_case + 2'h0: dout = csr; + 2'h1: dout = int; + 2'h2: dout = buf0; + 2'h3: dout = buf1; + endcase + +assign we0 = (adr==2'h0) & we; +assign we1 = (adr==2'h1) & we; +assign we2 = (adr==2'h2) & we; +assign we3 = (adr==2'h3) & we; + +// Endpoint CSR Register +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) + begin + csr0 <= 13'h0; + csr1 <= 13'h0; + ots_stop <= 1'b0; + end + else + if(we0) + begin + csr0 <= din[12:0]; + ots_stop <= din[13]; + csr1 <= din[27:15]; + end + else + if(ots_stop && out_to_small) + csr1[8:7] <= 2'b01; + +// Endpoint Interrupt Register +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) + begin + ienb <= 6'h0; + iena <= 6'h0; + end + else + if(we1) + begin + ienb <= din[21:16]; + iena <= din[29:24]; + end + +// Endpoint Buffer Registers +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) buf0 <= 32'hffff_ffff; + else + if(we2) buf0 <= din; + else + if(ep_match_r && buf0_rl) buf0 <= buf0_orig; + else + if(ep_match_r && buf0_set) buf0 <= idin; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) buf1 <= 32'hffff_ffff; + else + if(we3) buf1 <= din; + else + if(ep_match_r && + (buf1_set || out_to_small)) buf1 <= idin; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) buf0_orig <= 32'hffff_ffff; + else + if(we2) buf0_orig <= din; + +/////////////////////////////////////////////////////////////////// +// +// Internal Access +// + + +// Indicates that this register file matches the current +// endpoint from token +assign ep_match = (ep_sel == csr[21:18]); + +always @(posedge clk) + ep_match_r <= ep_match; + +always @(posedge clk) + int_re <= re & (adr == 2'h1); + +// Interrupt Sources +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) int_stat <= 7'h0; + else + if(int_re) int_stat <= 7'h0; + else + if(ep_match_r) + begin + if(out_to_small) int_stat[6] <= 1'b1; + if(int_seqerr_set) int_stat[5] <= 1'b1; + if(int_buf1_set) int_stat[4] <= 1'b1; + if(int_buf0_set) int_stat[3] <= 1'b1; + if(int_upid_set) int_stat[2] <= 1'b1; + if(int_crc16_set) int_stat[1] <= 1'b1; + if(int_to_set) int_stat[0] <= 1'b1; + end + +// PID toggle track bits +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) uc_dpd <= 2'h0; + else + if(ep_match_r && uc_dpd_set) uc_dpd <= idin[3:2]; + +// Buffer toggle track bits +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) uc_bsel <= 2'h0; + else + if(ep_match_r && uc_bsel_set) uc_bsel <= idin[1:0]; + +/////////////////////////////////////////////////////////////////// +// +// Endpoint Interrupt Generation +// + +always @(posedge wclk) + inta <= (int_stat[0] & iena[0]) | + (int_stat[1] & iena[1]) | + (int_stat[2] & iena[2]) | + (int_stat[3] & iena[3]) | + (int_stat[4] & iena[3]) | + (int_stat[5] & iena[4]) | + (int_stat[6] & iena[5]); + +always @(posedge wclk) + intb <= (int_stat[0] & ienb[0]) | + (int_stat[1] & ienb[1]) | + (int_stat[2] & ienb[2]) | + (int_stat[3] & ienb[3]) | + (int_stat[4] & ienb[3]) | + (int_stat[5] & ienb[4]) | + (int_stat[6] & ienb[5]); + +/////////////////////////////////////////////////////////////////// +// +// Endpoint DMA Request Logic +// + +// DMA OUT endpoint counter +always @(posedge clk) + if(!dma_en) dma_out_cnt <= 12'h0; + else + if(dma_ack_i) dma_out_cnt <= dma_out_cnt - 12'h1; + else + if(ep_match_r && (set_r || buf0_set || buf0_rl)) + dma_out_cnt <= dma_out_cnt + {3'h0, max_pl_sz[10:2]}; + +// If buf0_set or buf0_rl was asserted at the same time as dma_ack_i +// remember it and perform the add next cycle ... +always @(posedge clk) + set_r <= dma_ack_i & (buf0_set | buf0_rl); + +// This signal is used to keep dma_req asserted when we know there is +// plenty of data in the buffer. +// When the buffer is "low", we do one dma_req and wait to see if there +// is more data and repeat until the buffer is empty. +// This is because of the sync logic - it has to propagate first +// before we can determine that the buffer is really empty. +always @(posedge wclk) + dma_req_out_hold <= |dma_out_cnt[11:2] & ep_out; + +assign dma_out_cnt_is_zero = dma_out_cnt == 12'h0; + +// DMA IN endpoint counter +always @(posedge clk) + if(!dma_en) dma_in_cnt <= 12'h0; + else + if(dma_ack_i) dma_in_cnt <= dma_in_cnt + 12'h1; + else + if(ep_match_r && (set_r || buf0_set || buf0_rl)) + dma_in_cnt <= dma_in_cnt - {3'h0, max_pl_sz[10:2]}; + +// Indicates to Protocol Engine when we have gotten at least one packet in to buffer +// This is for IN transfers only +always @(posedge clk) + dma_in_buf_sz1 <= (dma_in_cnt >= {3'h0,max_pl_sz[10:2]}) & + (max_pl_sz[10:0] != 11'h0); + +// Indicates to Protocol Engine that there is space for at least one MAX_PL_SZ +// packet in buffer. OUT transfers only. +always @(posedge clk) + dma_out_left <= (buf0_orig[30:19] - dma_out_cnt); + +always @(posedge clk) + dma_out_buf_avail <= (dma_out_left >= {3'h0, max_pl_sz[10:2]}); + +// DMA Request Generation +assign dma_req_d = dma_en & (dma_req_in_d | dma_req_out_d); + +// For OUT +assign dma_req_out_d = ep_out & !dma_out_cnt_is_zero; + +// FOR IN +assign dma_req_in_d = ep_in & (dma_in_cnt < buf0_orig[30:19]); + + +always @(posedge wclk) + buf0_orig_m3 <= buf0_orig[30:19] - 12'h3; + +reg dma_req_in_hold2; + +always @(posedge wclk) + dma_req_in_hold2 <= (dma_in_cnt < buf0_orig_m3); + +always @(posedge wclk) + dma_req_in_hold <= ep_in & |buf0_orig[30:21]; + +assign dma_req_hold = ep_out ? dma_req_out_hold : (dma_req_in_hold & dma_req_in_hold2); + +// Generate a Sync. Request +assign dma_req = dma_req_r; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) dma_req_r <= 1'b0; + else + if(r1 && !r2) dma_req_r <= 1'b1; + else + if(dma_ack && !dma_req_hold) dma_req_r <= 1'b0; + +always @(posedge wclk) + r1 <= dma_req_d & !r2 & !r4 & !r5; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) r2 <= 1'b0; + else + if(r1) r2 <= 1'b1; + else + if(r4) r2 <= 1'b0; + +// Synchronize ACK +reg dma_ack_wr1; +reg dma_ack_clr1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) dma_ack_wr1 <= 1'b0; + else + if(dma_ack) dma_ack_wr1 <= 1'b1; + else + if(dma_ack_clr1) dma_ack_wr1 <= 1'b0; + +always @(posedge wclk) + dma_ack_clr1 <= r4; + +always @(posedge clk) + r4 <= dma_ack_wr1; + +always @(posedge clk) + r5 <= r4; + +assign dma_ack_i = r5; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v new file mode 100644 index 000000000..e486792ea --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v @@ -0,0 +1,152 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Dummy Endpoint register File //// +//// This module contains termination for registers in ONE //// +//// endpoint. It is used to replace the actual endpoint //// +//// register file for non existing endpoints. //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_ep_rf_dummy.v,v 1.2 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_ep_rf_dummy.v,v $ +// Revision 1.2 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.1 2001/03/31 12:45:13 rudi +// +// This is the endpoint register file for non existing endpoints. It will be used for +// endpoints that are commented out in the usd_defines.v file. +// It will terminate all outputs to a known good level ... +// +// +// + +`include "usbf_defines.v" + +// Endpoint register File +module usbf_ep_rf_dummy( + clk, wclk, rst, + + // Wishbone Interface + adr, re, we, din, dout, inta, intb, + dma_req, dma_ack, + + // Internal Interface + + idin, + ep_sel, ep_match, + buf0_rl, buf0_set, buf1_set, + uc_bsel_set, uc_dpd_set, + + int_buf1_set, int_buf0_set, int_upid_set, + int_crc16_set, int_to_set, int_seqerr_set, + out_to_small, + + csr, buf0, buf1, dma_in_buf_sz1, dma_out_buf_avail + ); + +input clk, wclk, rst; +input [1:0] adr; +input re; +input we; +input [31:0] din; +output [31:0] dout; +output inta, intb; +output dma_req; +input dma_ack; + +input [31:0] idin; // Data Input +input [3:0] ep_sel; // Endpoint Number Input +output ep_match; // Asserted to indicate a ep no is matched +input buf0_rl; // Reload Buf 0 with original values + +input buf0_set; // Write to buf 0 +input buf1_set; // Write to buf 1 +input uc_bsel_set; // Write to the uc_bsel field +input uc_dpd_set; // Write to the uc_dpd field +input int_buf1_set; // Set buf1 full/empty interrupt +input int_buf0_set; // Set buf0 full/empty interrupt +input int_upid_set; // Set unsupported PID interrupt +input int_crc16_set; // Set CRC16 error interrupt +input int_to_set; // Set time out interrupt +input int_seqerr_set; // Set PID sequence error interrupt +input out_to_small; // OUT packet was to small for DMA operation + +output [31:0] csr; // Internal CSR Output +output [31:0] buf0; // Internal Buf 0 Output +output [31:0] buf1; // Internal Buf 1 Output +output dma_in_buf_sz1; // Indicates that the DMA IN buffer has 1 max_pl_sz + // packet available +output dma_out_buf_avail;// Indicates that there is space for at least + // one MAX_PL_SZ packet in the buffer + +/////////////////////////////////////////////////////////////////// +// +// Internal Access +// + +assign dout = 32'h0; +assign inta = 1'b0; +assign intb = 1'b0; +assign dma_req = 1'b0; +assign ep_match = 1'b0; +assign csr = 32'h0; +assign buf0 = 32'hffff_ffff; +assign buf1 = 32'hffff_ffff; +assign dma_in_buf_sz1 = 1'b0; +assign dma_out_buf_avail = 1'b0; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v new file mode 100644 index 000000000..68d525f16 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v @@ -0,0 +1,636 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Internal DMA Engine //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_idma.v,v 1.8 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.8 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_idma.v,v $ +// Revision 1.8 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.7 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.6 2001/11/03 03:26:22 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.5 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.4 2001/09/23 08:39:33 rudi +// +// Renamed DEBUG and VERBOSE_DEBUG to USBF_DEBUG and USBF_VERBOSE_DEBUG ... +// +// Revision 1.3 2001/09/19 14:38:57 rudi +// +// Fixed TxValid handling bug. +// +// Revision 1.2 2001/09/13 13:14:02 rudi +// +// Fixed a problem that would sometimes prevent the core to come out of +// reset and immediately be operational ... +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:51 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:50 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_idma( clk, rst, + + // Packet Disassembler/Assembler interface + rx_data_st, rx_data_valid, rx_data_done, + send_data, tx_data_st, rd_next, + + // Protocol Engine + rx_dma_en, tx_dma_en, + abort, idma_done, + buf_size, dma_en, + send_zero_length, + + // Register File Manager Interface + adr, size, sizu_c, + + // Memory Arb interface + madr, mdout, mdin, mwe, mreq, mack + ); + +parameter SSRAM_HADR = 14; + +// Packet Disassembler/Assembler interface +input clk, rst; +input [7:0] rx_data_st; +input rx_data_valid; +input rx_data_done; +output send_data; +output [7:0] tx_data_st; +input rd_next; + +// Protocol Engine +input rx_dma_en; // Allows the data to be stored +input tx_dma_en; // Allows for data to be retrieved +input abort; // Abort Transfer (time_out, crc_err or rx_error) +output idma_done; // DMA is done +input [13:0] buf_size; // Actual buffer size +input dma_en; // External DMA enabled +input send_zero_length; + +// Register File Manager Interface +input [SSRAM_HADR + 2:0] adr; // Byte Address +input [13:0] size; // Size in bytes +output [10:0] sizu_c; // Up and Down counting size registers, used to update + +// Memory Arb interface +output [SSRAM_HADR:0] madr; // word address +output [31:0] mdout; +input [31:0] mdin; +output mwe; +output mreq; +input mack; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [7:0] // synopsys enum state + IDLE = 8'b00000001, + WAIT_MRD = 8'b00000010, + MEM_WR = 8'b00000100, + MEM_WR1 = 8'b00001000, + MEM_WR2 = 8'b00010000, + MEM_RD1 = 8'b00100000, + MEM_RD2 = 8'b01000000, + MEM_RD3 = 8'b10000000; + +reg [7:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg tx_dma_en_r, rx_dma_en_r; + +reg [SSRAM_HADR:0] adr_cw; // Internal word address counter +reg [2:0] adr_cb; // Internal byte address counter +reg [SSRAM_HADR:0] adrw_next; // next address +reg [SSRAM_HADR:0] adrw_next1; // next address (after overrun check) +reg [SSRAM_HADR:0] last_buf_adr; // Last Buffer Address +reg [2:0] adrb_next; // next byte address +reg [13:0] sizd_c; // Internal size counter +reg [10:0] sizu_c; // Internal size counter +wire adr_incw; +wire adr_incb; +wire siz_dec; +wire siz_inc; + +reg word_done; // Indicates that a word has been + // assembled +reg mreq_d; // Memory request from State Machine +reg [31:0] dtmp_r; // Temp data assembly register +reg [31:0] dout_r; // Data output register +reg mwe_d; // Memory Write enable +reg dtmp_sel; // Selects tmp data register for pre-fetch + +reg sizd_is_zero; // Indicates when all bytes have been + // transferred +wire sizd_is_zero_d; + +reg [7:0] tx_data_st; // Data output to packet assembler +reg [31:0] rd_buf0, rd_buf1; // Mem Rd. buffers for TX +reg rd_first; // Indicates initial fill of buffers + +reg idma_done; // DMA transfer is done + +reg mack_r; +wire send_data; // Enable UTMI Transmitter +reg send_data_r; + +reg word_done_r; +reg wr_last; +reg wr_last_en; +reg wr_done; +reg wr_done_r; +reg dtmp_sel_r; +reg mwe; +reg rx_data_done_r2; +wire fill_buf0, fill_buf1; +wire adrb_is_3; + +reg rx_data_done_r; +reg rx_data_valid_r; +reg [7:0] rx_data_st_r; + +reg send_zero_length_r; + +/////////////////////////////////////////////////////////////////// +// +// Memory Arb interface +// + +// Memory Request +assign mreq = (mreq_d & !mack_r) | word_done_r; + +// Output Data +assign mdout = dout_r; + +// Memory Address +assign madr = adr_cw; + +always @(posedge clk) + mwe <= mwe_d; + +always @(posedge clk) + mack_r <= mreq & mack; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + rx_data_valid_r <= rx_data_valid; + +always @(posedge clk) + rx_data_st_r <= rx_data_st; + +always @(posedge clk) + rx_data_done_r <= rx_data_done; + +always @(posedge clk) + rx_data_done_r2 <= rx_data_done_r; + +// Generate one cycle pulses for tx and rx dma enable +always @(posedge clk) + tx_dma_en_r <= tx_dma_en; + +always @(posedge clk) + rx_dma_en_r <= rx_dma_en; + +always @(posedge clk) + send_zero_length_r <= send_zero_length; + +// address counter +always @(posedge clk) + if(rx_dma_en_r || tx_dma_en_r) adr_cw <= adr[SSRAM_HADR + 2:2]; + else adr_cw <= adrw_next1; + +always @(posedge clk) + last_buf_adr <= adr + { {SSRAM_HADR+2-13{1'b0}}, buf_size }; + +always @(dma_en or adrw_next or last_buf_adr) + if(adrw_next == last_buf_adr && dma_en) adrw_next1 = {SSRAM_HADR+1{1'b0}}; + else adrw_next1 = adrw_next; + +always @(adr_incw or adr_cw) + if(adr_incw) adrw_next = adr_cw + {{SSRAM_HADR{1'b0}}, 1'b1}; + else adrw_next = adr_cw; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) adr_cb <= 3'h0; + else + if(rx_dma_en_r || tx_dma_en_r) adr_cb <= adr[2:0]; + else adr_cb <= adrb_next; + +always @(adr_incb or adr_cb) + if(adr_incb) adrb_next = adr_cb + 3'h1; + else adrb_next = adr_cb; + +assign adr_incb = rx_data_valid_r | rd_next; +assign adr_incw = !dtmp_sel_r & mack_r; + +// Size Counter (counting backward from input size) +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sizd_c <= 14'h3fff; + else + if(tx_dma_en || tx_dma_en_r) sizd_c <= size; + else + if(siz_dec) sizd_c <= sizd_c - 14'h1; + +assign siz_dec = (rd_first & mack_r) | (rd_next & (sizd_c != 14'h0)); + +assign sizd_is_zero_d = sizd_c == 14'h0; + +always @(posedge clk) + sizd_is_zero <= sizd_is_zero_d; + +// Size Counter (counting up from zero) +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sizu_c <= 11'h0; + else + // Do I need to add "abort" in the next line ??? + if(rx_dma_en_r) sizu_c <= 11'h0; + else + if(siz_inc) sizu_c <= sizu_c + 11'h1; + +assign siz_inc = rx_data_valid_r; + +// DMA Done Indicator +always @(posedge clk) + idma_done <= (rx_data_done_r | sizd_is_zero_d); // & !tx_dma_en; + +/////////////////////////////////////////////////////////////////// +// +// RX Logic +// + +always @(posedge clk) + dtmp_sel_r <= dtmp_sel; + +// Memory data input +always @(posedge clk) + if(dtmp_sel_r) dtmp_r <= mdin; + else + if(rx_data_valid_r) + begin + if(adr_cb[1:0] == 2'h0) dtmp_r[07:00] <= rx_data_st_r; + if(adr_cb[1:0] == 2'h1) dtmp_r[15:08] <= rx_data_st_r; + if(adr_cb[1:0] == 2'h2) dtmp_r[23:16] <= rx_data_st_r; + if(adr_cb[1:0] == 2'h3) dtmp_r[31:24] <= rx_data_st_r; + end + +always @(posedge clk) + word_done <= ((adr_cb[1:0] == 2'h3) & rx_data_valid_r) | wr_last; + +always @(posedge clk) + word_done_r <= word_done & !word_done_r; + +// Store output data and address when we got a word +always @(posedge clk) + if(word_done) dout_r <= dtmp_r; + +always @(posedge clk) + wr_last <= (adr_cb[1:0] != 2'h0) & !rx_data_valid_r & wr_last_en; + +always @(posedge clk) + wr_done_r <= rx_data_done_r; + +always @(posedge clk) + wr_done <= wr_done_r; + +/////////////////////////////////////////////////////////////////// +// +// TX Logic +// + +// Fill TX Buffers +always @(posedge clk) + if(fill_buf0) rd_buf0 <= mdin; + +always @(posedge clk) + if(fill_buf1) rd_buf1 <= mdin; + +always @(adrb_next or rd_buf0 or rd_buf1) + case(adrb_next[2:0]) // synopsys full_case parallel_case + 3'h0: tx_data_st = rd_buf0[07:00]; + 3'h1: tx_data_st = rd_buf0[15:08]; + 3'h2: tx_data_st = rd_buf0[23:16]; + 3'h3: tx_data_st = rd_buf0[31:24]; + 3'h4: tx_data_st = rd_buf1[07:00]; + 3'h5: tx_data_st = rd_buf1[15:08]; + 3'h6: tx_data_st = rd_buf1[23:16]; + 3'h7: tx_data_st = rd_buf1[31:24]; + endcase + +assign fill_buf0 = !adr_cw[0] & mack_r; +assign fill_buf1 = adr_cw[0] & mack_r; + +assign adrb_is_3 = adr_cb[1:0] == 2'h3; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) send_data_r <= 1'b0; + else + if(rd_first) send_data_r <= 1'b1; + else + if(((sizd_c==14'h1) && rd_next) || sizd_is_zero_d) send_data_r <= 1'b0; + +assign send_data = send_data_r | send_zero_length_r; + +/////////////////////////////////////////////////////////////////// +// +// IDMA Load/Store State Machine +// + +// store incoming data to memory until rx_data done +// First pre-fetch data from memory, so that bytes can be stuffed properly + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or mack_r or abort or rx_dma_en_r or tx_dma_en_r or + sizd_is_zero or wr_last or wr_done or rx_data_done_r2 or + rd_next or adrb_is_3 or send_zero_length_r) + begin + next_state = state; // Default do not change state + mreq_d = 1'b0; + mwe_d = 1'b0; + rd_first = 1'b0; + dtmp_sel = 1'b0; + wr_last_en = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered IDLE state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(rst) +begin +if(rx_dma_en_r === 1'bx) $display("ERROR: IDMA: IDLE: rx_dma_en_r is unknown. (%t)", $time); +if(tx_dma_en_r === 1'bx) $display("ERROR: IDMA: IDLE: tx_dma_en_r is unknown. (%t)", $time); +if(abort === 1'bx) $display("ERROR: IDMA: IDLE: abort is unknown. (%t)", $time); +end +`endif +// synopsys translate_on + + if(rx_dma_en_r && !abort) + begin + next_state = WAIT_MRD; + end + if(tx_dma_en_r && !abort && !send_zero_length_r) + begin + next_state = MEM_RD1; + end + end + + WAIT_MRD: // Pre-fetch a word from memory + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered WAIT_MRD state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: WAIT_MRD: abort is unknown. (%t)", $time); +if(mack_r === 1'bx) $display("ERROR: IDMA: WAIT_MRD: mack_r is unknown. (%t)", $time); +`endif +// synopsys translate_on + + if(abort) next_state = IDLE; + else + if(mack_r) next_state = MEM_WR; + else + begin + dtmp_sel = 1'b1; + mreq_d = 1'b1; + end + end + + MEM_WR: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_WR state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: MEM_WR: abort is unknown. (%t)", $time); +if(rx_data_done_r2 === 1'bx) $display("ERROR: IDMA: MEM_WR: rx_data_done_r2 is unknown. (%t)", $time); +`endif +// synopsys translate_on + + mwe_d = 1'b1; + if(abort) next_state = IDLE; + else + if(rx_data_done_r2) + begin + wr_last_en = 1'b1; + next_state = MEM_WR1; + end + + end + MEM_WR1: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_WR1 state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: MEM_WR1: abort is unknown. (%t)", $time); +if(wr_last === 1'bx) $display("ERROR: IDMA: MEM_WR1: wr_last is unknown. (%t)", $time); +if(wr_done === 1'bx) $display("ERROR: IDMA: MEM_WR1: wr_done is unknown. (%t)", $time); +`endif +// synopsys translate_on + + mwe_d = 1'b1; + wr_last_en = 1'b1; + if(abort) next_state = IDLE; + else + if(wr_last) next_state = MEM_WR2; + else + if(wr_done) next_state = IDLE; + end + + MEM_WR2: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_WR2 state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_WR2: mack_r is unknown. (%t)", $time); +`endif +// synopsys translate_on + + mwe_d = 1'b1; + if(mack_r) next_state = IDLE; + end + + MEM_RD1: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_RD1 state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD1: abort is unknown. (%t)", $time); +if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_RD1: mack_r is unknown. (%t)", $time); +`endif +// synopsys translate_on + + mreq_d = 1'b1; + if(mack_r) rd_first = 1'b1; + if(abort) next_state = IDLE; + else + if(mack_r) next_state = MEM_RD2; + end + MEM_RD2: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_RD2 state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD2: abort is unknown. (%t)", $time); +if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_RD2: mack_r is unknown. (%t)", $time); +`endif +// synopsys translate_on + + mreq_d = 1'b1; + if(abort) next_state = IDLE; + else + if(mack_r) next_state = MEM_RD3; + end + MEM_RD3: + begin + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +$display("IDMA: Entered MEM_RD3 state (%t)", $time); +`endif +`ifdef USBF_DEBUG +if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD3: abort is unknown. (%t)", $time); +if(sizd_is_zero===1'bx) $display("ERROR: IDMA: MEM_RD3: sizd_is_zero is unknown. (%t)", $time); +if(adrb_is_3 === 1'bx) $display("ERROR: IDMA: MEM_RD3: adrb_is_3 is unknown. (%t)", $time); +if(rd_next === 1'bx) $display("ERROR: IDMA: MEM_RD3: rd_next is unknown. (%t)", $time); +`endif +// synopsys translate_on + + if(sizd_is_zero || abort) next_state = IDLE; + else + if(adrb_is_3 && rd_next) next_state = MEM_RD2; + end + endcase + + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v new file mode 100644 index 000000000..c5fc24254 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v @@ -0,0 +1,196 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Memory Buffer Arbiter //// +//// Arbitrates between the internal DMA and external bus //// +//// interface for the internal buffer memory //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_mem_arb.v,v 1.3 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_mem_arb.v,v $ +// Revision 1.3 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.2 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:51 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:52 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_mem_arb( phy_clk, wclk, rst, + + // SSRAM Interface + sram_adr, sram_din, sram_dout, sram_re, sram_we, + + // IDMA Memory Interface + madr, mdout, mdin, mwe, mreq, mack, + + // WISHBONE Memory Interface + wadr, wdout, wdin, wwe, wreq, wack + + ); + +parameter SSRAM_HADR = 14; + +input phy_clk, wclk, rst; + +output [SSRAM_HADR:0] sram_adr; +input [31:0] sram_din; +output [31:0] sram_dout; +output sram_re, sram_we; + +input [SSRAM_HADR:0] madr; +output [31:0] mdout; +input [31:0] mdin; +input mwe; +input mreq; +output mack; + +input [SSRAM_HADR:0] wadr; +output [31:0] wdout; +input [31:0] wdin; +input wwe; +input wreq; +output wack; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +wire wsel; +reg [SSRAM_HADR:0] sram_adr; +reg [31:0] sram_dout; +reg sram_we; +wire mack; +wire mcyc; +reg wack_r; + +/////////////////////////////////////////////////////////////////// +// +// Memory Arbiter Logic +// + +// IDMA has always first priority + +// ----------------------------------------- +// Ctrl Signals + +assign wsel = (wreq | wack) & !mreq; + +// ----------------------------------------- +// SSRAM Specific +// Data Path +always @(wsel or wdin or mdin) + if(wsel) sram_dout = wdin; + else sram_dout = mdin; + +// Address Path +always @(wsel or wadr or madr) + if(wsel) sram_adr = wadr; + else sram_adr = madr; + +// Write Enable Path +always @(wsel or wwe or wreq or mwe or mcyc) + if(wsel) sram_we = wreq & wwe; + else sram_we = mwe & mcyc; + +assign sram_re = 1'b1; + +// ----------------------------------------- +// IDMA specific + +assign mdout = sram_din; + +assign mack = mreq; + +assign mcyc = mack; // Qualifier for writes + +// ----------------------------------------- +// WISHBONE specific +assign wdout = sram_din; + +assign wack = wack_r & !mreq; + +`ifdef USBF_ASYNC_RESET +always @(posedge phy_clk or negedge rst) +`else +always @(posedge phy_clk) +`endif + if(!rst) wack_r <= 1'b0; + else wack_r <= wreq & !mreq & !wack; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v new file mode 100644 index 000000000..c3231d840 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v @@ -0,0 +1,386 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Packet Assembler //// +//// Assembles Token and Data USB packets //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_pa.v,v 1.6 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_pa.v,v $ +// Revision 1.6 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.5 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.4 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.3 2001/09/19 14:38:57 rudi +// +// Fixed TxValid handling bug. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:54 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_pa( clk, rst, + + // UTMI TX I/F + tx_data, tx_valid, tx_valid_last, tx_ready, + tx_first, + + // Protocol Engine Interface + send_token, token_pid_sel, + send_data, data_pid_sel, + send_zero_length, + + // IDMA Interface + tx_data_st, rd_next + ); + +input clk, rst; + +// UTMI TX Interface +output [7:0] tx_data; +output tx_valid; +output tx_valid_last; +input tx_ready; +output tx_first; + +// Protocol Engine Interface +input send_token; +input [1:0] token_pid_sel; +input send_data; +input [1:0] data_pid_sel; +input send_zero_length; + +// IDMA Interface +input [7:0] tx_data_st; +output rd_next; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [4:0] // synopsys enum state + IDLE = 5'b00001, + DATA = 5'b00010, + CRC1 = 5'b00100, + CRC2 = 5'b01000, + WAIT = 5'b10000; + +reg [4:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg last; +reg rd_next; + +reg [7:0] token_pid, data_pid; // PIDs from selectors +reg [7:0] tx_data_d; +reg [7:0] tx_data_data; +reg dsel; +reg tx_valid_d; +reg send_token_r; +reg [7:0] tx_spec_data; +reg crc_sel1, crc_sel2; +reg tx_first_r; +reg send_data_r; +wire crc16_clr; +reg [15:0] crc16; +wire [15:0] crc16_next; +wire [15:0] crc16_rev; +wire crc16_add; +reg send_data_r2; +reg tx_valid_r; +reg tx_valid_r1; +reg zero_length_r; +reg send_zero_length_r; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + send_zero_length_r <= send_zero_length; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) zero_length_r <= 1'b0; + else + if(last) zero_length_r <= 1'b0; + else + if(crc16_clr) zero_length_r <= send_zero_length_r; + +always @(posedge clk) + tx_valid_r1 <= tx_valid; + +always @(posedge clk) + tx_valid_r <= tx_valid_r1; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) send_token_r <= 1'b0; + else + if(send_token) send_token_r <= 1'b1; + else + if(tx_ready) send_token_r <= 1'b0; + +// PID Select +always @(token_pid_sel) + case(token_pid_sel) // synopsys full_case parallel_case + 2'd0: token_pid = { ~`USBF_T_PID_ACK, `USBF_T_PID_ACK}; + 2'd1: token_pid = { ~`USBF_T_PID_NACK, `USBF_T_PID_NACK}; + 2'd2: token_pid = {~`USBF_T_PID_STALL, `USBF_T_PID_STALL}; + 2'd3: token_pid = { ~`USBF_T_PID_NYET, `USBF_T_PID_NYET}; + endcase + +always @(data_pid_sel) + case(data_pid_sel) // synopsys full_case parallel_case + 2'd0: data_pid = { ~`USBF_T_PID_DATA0, `USBF_T_PID_DATA0}; + 2'd1: data_pid = { ~`USBF_T_PID_DATA1, `USBF_T_PID_DATA1}; + 2'd2: data_pid = { ~`USBF_T_PID_DATA2, `USBF_T_PID_DATA2}; + 2'd3: data_pid = { ~`USBF_T_PID_MDATA, `USBF_T_PID_MDATA}; + endcase + +// Data path Muxes + +always @(send_token or send_token_r or token_pid or tx_data_data) + if(send_token || send_token_r) tx_data_d = token_pid; + else tx_data_d = tx_data_data; + +always @(dsel or tx_data_st or tx_spec_data) + if(dsel) tx_data_data = tx_spec_data; + else tx_data_data = tx_data_st; + +always @(crc_sel1 or crc_sel2 or data_pid or crc16_rev) + if(!crc_sel1 && !crc_sel2) tx_spec_data = data_pid; + else + if(crc_sel1) tx_spec_data = crc16_rev[15:8]; // CRC 1 + else tx_spec_data = crc16_rev[7:0]; // CRC 2 + +assign tx_data = tx_data_d; + +// TX Valid assignment +assign tx_valid_last = send_token | last; +assign tx_valid = tx_valid_d; + +always @(posedge clk) + tx_first_r <= send_token | send_data; + +assign tx_first = (send_token | send_data) & ! tx_first_r; + +// CRC Logic +always @(posedge clk) + send_data_r <= send_data; + +always @(posedge clk) + send_data_r2 <= send_data_r; + +assign crc16_clr = send_data & !send_data_r; + +assign crc16_add = !zero_length_r & (send_data_r & !send_data_r2) | (rd_next & !crc_sel1); + +always @(posedge clk) + if(crc16_clr) crc16 <= 16'hffff; + else + if(crc16_add) crc16 <= crc16_next; + + +usbf_crc16 u1( + .crc_in( crc16 ), + .din( {tx_data_st[0], tx_data_st[1], + tx_data_st[2], tx_data_st[3], + tx_data_st[4], tx_data_st[5], + tx_data_st[6], tx_data_st[7]} ), + .crc_out( crc16_next ) ); + +assign crc16_rev[15] = ~crc16[8]; +assign crc16_rev[14] = ~crc16[9]; +assign crc16_rev[13] = ~crc16[10]; +assign crc16_rev[12] = ~crc16[11]; +assign crc16_rev[11] = ~crc16[12]; +assign crc16_rev[10] = ~crc16[13]; +assign crc16_rev[9] = ~crc16[14]; +assign crc16_rev[8] = ~crc16[15]; +assign crc16_rev[7] = ~crc16[0]; +assign crc16_rev[6] = ~crc16[1]; +assign crc16_rev[5] = ~crc16[2]; +assign crc16_rev[4] = ~crc16[3]; +assign crc16_rev[3] = ~crc16[4]; +assign crc16_rev[2] = ~crc16[5]; +assign crc16_rev[1] = ~crc16[6]; +assign crc16_rev[0] = ~crc16[7]; + +/////////////////////////////////////////////////////////////////// +// +// Transmit/Encode state machine +// + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or send_data or tx_ready or tx_valid_r or send_zero_length_r) + begin + next_state = state; // Default don't change current state + tx_valid_d = 1'b0; + dsel = 1'b0; + rd_next = 1'b0; + last = 1'b0; + crc_sel1 = 1'b0; + crc_sel2 = 1'b0; + case(state) // synopsys full_case parallel_case + IDLE: + begin + if(send_zero_length_r && send_data) + begin + tx_valid_d = 1'b1; + next_state = WAIT; + dsel = 1'b1; + end + else + if(send_data) // Send DATA packet + begin + tx_valid_d = 1'b1; + next_state = DATA; + dsel = 1'b1; + end + end + DATA: + begin + if(tx_ready && tx_valid_r) + rd_next = 1'b1; + + tx_valid_d = 1'b1; + if(!send_data && tx_ready && tx_valid_r) + begin + dsel = 1'b1; + crc_sel1 = 1'b1; + next_state = CRC1; + end + end + WAIT: // In case of early tx_ready ... + begin + crc_sel1 = 1'b1; + dsel = 1'b1; + tx_valid_d = 1'b1; + next_state = CRC1; + end + CRC1: + begin + dsel = 1'b1; + tx_valid_d = 1'b1; + if(tx_ready) + begin + last = 1'b1; + crc_sel2 = 1'b1; + next_state = CRC2; + end + else + begin + tx_valid_d = 1'b1; + crc_sel1 = 1'b1; + end + + end + CRC2: + begin + dsel = 1'b1; + crc_sel2 = 1'b1; + if(tx_ready) + begin + next_state = IDLE; + end + else + begin + last = 1'b1; + end + + end + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v new file mode 100644 index 000000000..cbc0a97aa --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v @@ -0,0 +1,437 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Packet Disassembler //// +//// Disassembles Token and Data USB packets //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_pd.v,v 1.7 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.7 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_pd.v,v $ +// Revision 1.7 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.5 2001/11/03 03:26:22 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.4 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.3 2001/09/10 15:54:20 rudi +// +// Fixed crc5 checking. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:51 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:10:59 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_pd( clk, rst, + + // UTMI RX I/F + rx_data, rx_valid, rx_active, rx_err, + + // PID Information + pid_OUT, pid_IN, pid_SOF, pid_SETUP, + pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, + pid_ACK, pid_NACK, pid_STALL, pid_NYET, + pid_PRE, pid_ERR, pid_SPLIT, pid_PING, + pid_cks_err, + + // Token Information + token_fadr, token_endp, token_valid, crc5_err, + frame_no, + + // Receive Data Output + rx_data_st, rx_data_valid, rx_data_done, crc16_err, + + // Misc. + seq_err + ); + +input clk, rst; + + //UTMI RX Interface +input [7:0] rx_data; +input rx_valid, rx_active, rx_err; + + // Decoded PIDs (used when token_valid is asserted) +output pid_OUT, pid_IN, pid_SOF, pid_SETUP; +output pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +output pid_ACK, pid_NACK, pid_STALL, pid_NYET; +output pid_PRE, pid_ERR, pid_SPLIT, pid_PING; +output pid_cks_err; // Indicates a PID checksum error + + +output [6:0] token_fadr; // Function address from token +output [3:0] token_endp; // Endpoint number from token +output token_valid; // Token is valid +output crc5_err; // Token crc5 error +output [10:0] frame_no; // Frame number for SOF tokens + +output [7:0] rx_data_st; // Data to memory store unit +output rx_data_valid; // Data on rx_data_st is valid +output rx_data_done; // Indicates end of a transfer +output crc16_err; // Data packet CRC 16 error + +output seq_err; // State Machine Sequence Error + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [3:0] // synopsys enum state + IDLE = 4'b0001, + ACTIVE = 4'b0010, + TOKEN = 4'b0100, + DATA = 4'b1000; + +reg [3:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg [7:0] pid; // Packet PDI +reg pid_le_sm; // PID Load enable from State Machine +wire pid_ld_en; // Enable loading of PID (all conditions) +wire pid_cks_err; // Indicates a pid checksum err + + // Decoded PID values +wire pid_OUT, pid_IN, pid_SOF, pid_SETUP; +wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +wire pid_ACK, pid_NACK, pid_STALL, pid_NYET; +wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING, pid_RES; +wire pid_TOKEN; // All TOKEN packet that we recognize +wire pid_DATA; // All DATA packets that we recognize + +reg [7:0] token0, token1; // Token Registers +reg token_le_1, token_le_2; // Latch enables for token storage registers +wire [4:0] token_crc5; + +reg [7:0] d0, d1, d2; // Data path delay line (used to filter out crcs) +reg data_valid_d; // Data Valid output from State Machine +reg data_done; // Data cycle complete output from State Machine +reg data_valid0; // Data valid delay line +reg rxv1; +reg rxv2; + +reg seq_err; // State machine sequence error + +reg got_pid_ack; + +reg token_valid_r1; +reg token_valid_str1; + +reg rx_active_r; + +wire [4:0] crc5_out; +wire [4:0] crc5_out2; +wire crc16_clr; +reg [15:0] crc16_sum; +wire [15:0] crc16_out; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// PID Decoding Logic +assign pid_ld_en = pid_le_sm & rx_active & rx_valid; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) pid <= 8'hf0; + else + if(pid_ld_en) pid <= rx_data; + +assign pid_cks_err = (pid[3:0] != ~pid[7:4]); + +assign pid_OUT = pid[3:0] == `USBF_T_PID_OUT; +assign pid_IN = pid[3:0] == `USBF_T_PID_IN; +assign pid_SOF = pid[3:0] == `USBF_T_PID_SOF; +assign pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP; +assign pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0; +assign pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1; +assign pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2; +assign pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA; +assign pid_ACK = pid[3:0] == `USBF_T_PID_ACK; +assign pid_NACK = pid[3:0] == `USBF_T_PID_NACK; +assign pid_STALL = pid[3:0] == `USBF_T_PID_STALL; +assign pid_NYET = pid[3:0] == `USBF_T_PID_NYET; +assign pid_PRE = pid[3:0] == `USBF_T_PID_PRE; +assign pid_ERR = pid[3:0] == `USBF_T_PID_ERR; +assign pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT; +assign pid_PING = pid[3:0] == `USBF_T_PID_PING; +assign pid_RES = pid[3:0] == `USBF_T_PID_RES; + +assign pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING; +assign pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA; + +// Token Decoding LOGIC +always @(posedge clk) + if(token_le_1) token0 <= rx_data; + +always @(posedge clk) + if(token_le_2) token1 <= rx_data; + +always @(posedge clk) + token_valid_r1 <= token_le_2; + +always @(posedge clk) + token_valid_str1 <= token_valid_r1 | got_pid_ack; + +assign token_valid = token_valid_str1; + +// CRC 5 should perform the check in one cycle (flow through logic) +// 11 bits and crc5 input, 1 bit output +assign crc5_err = token_valid & (crc5_out2 != token_crc5); + +usbf_crc5 u0( + .crc_in( 5'h1f ), + .din( { token_fadr[0], + token_fadr[1], + token_fadr[2], + token_fadr[3], + token_fadr[4], + token_fadr[5], + token_fadr[6], + token_endp[0], + token_endp[1], + token_endp[2], + token_endp[3] } ), + .crc_out( crc5_out ) ); + +// Invert and reverse result bits +assign crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3], + crc5_out[4]}; + +assign frame_no = { token1[2:0], token0}; +assign token_fadr = token0[6:0]; +assign token_endp = {token1[2:0], token0[7]}; +assign token_crc5 = token1[7:3]; + +// Data receiving logic +// build a delay line and stop when we are about to get crc +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rxv1 <= 1'b0; + else + if(data_valid_d) rxv1 <= 1'b1; + else + if(data_done) rxv1 <= 1'b0; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rxv2 <= 1'b0; + else + if(rxv1 && data_valid_d)rxv2 <= 1'b1; + else + if(data_done) rxv2 <= 1'b0; + +always @(posedge clk) + data_valid0 <= rxv2 & data_valid_d; + +always @(posedge clk) + begin + if(data_valid_d) d0 <= rx_data; + if(data_valid_d) d1 <= d0; + if(data_valid_d) d2 <= d1; + end + +assign rx_data_st = d2; +assign rx_data_valid = data_valid0; +assign rx_data_done = data_done; + +// crc16 accumulates rx_data as long as data_valid_d is asserted. +// when data_done is asserted, crc16 reports status, and resets itself +// next cycle. +always @(posedge clk) + rx_active_r <= rx_active; + +assign crc16_clr = rx_active & !rx_active_r; + +always @(posedge clk) + if(crc16_clr) crc16_sum <= 16'hffff; + else + if(data_valid_d) crc16_sum <= crc16_out; + +usbf_crc16 u1( + .crc_in( crc16_sum ), + .din( {rx_data[0], rx_data[1], rx_data[2], rx_data[3], + rx_data[4], rx_data[5], rx_data[6], rx_data[7]} ), + .crc_out( crc16_out ) ); + +// Verify against polynomial +assign crc16_err = data_done & (crc16_sum != 16'h800d); + +/////////////////////////////////////////////////////////////////// +// +// Receive/Decode State machine +// + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN + or pid_DATA) + begin + next_state = state; // Default don't change current state + pid_le_sm = 1'b0; + token_le_1 = 1'b0; + token_le_2 = 1'b0; + data_valid_d = 1'b0; + data_done = 1'b0; + seq_err = 1'b0; + got_pid_ack = 1'b0; + case(state) // synopsys full_case parallel_case + IDLE: + begin + pid_le_sm = 1'b1; + if(rx_valid && rx_active) next_state = ACTIVE; + end + ACTIVE: + begin + // Received a ACK from Host + if(pid_ACK && !rx_err) + begin + got_pid_ack = 1'b1; + if(!rx_active) next_state = IDLE; + end + else + // Receiving a TOKEN + if(pid_TOKEN && rx_valid && rx_active && !rx_err) + begin + token_le_1 = 1'b1; + next_state = TOKEN; + end + else + // Receiving DATA + if(pid_DATA && rx_valid && rx_active && !rx_err) + begin + data_valid_d = 1'b1; + next_state = DATA; + end + else + if( !rx_active || rx_err || + (rx_valid && !(pid_TOKEN || pid_DATA)) ) + begin + seq_err = !rx_err; + if(!rx_active) next_state = IDLE; + end + end + TOKEN: + begin + if(rx_valid && rx_active && !rx_err) + begin + token_le_2 = 1'b1; + next_state = IDLE; + end + else + if(!rx_active || rx_err) + begin + seq_err = !rx_err; + if(!rx_active) next_state = IDLE; + end + end + DATA: + begin + if(rx_valid && rx_active && !rx_err) data_valid_d = 1'b1; + if(!rx_active || rx_err) + begin + data_done = 1'b1; + if(!rx_active) next_state = IDLE; + end + end + + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v new file mode 100644 index 000000000..756453fa4 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v @@ -0,0 +1,1095 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Protocol Engine //// +//// Performs automatic protocol functions //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_pe.v,v 1.8 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.8 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_pe.v,v $ +// Revision 1.8 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.7 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.6 2001/11/03 03:26:22 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.5 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.4 2001/09/23 08:39:33 rudi +// +// Renamed DEBUG and VERBOSE_DEBUG to USBF_DEBUG and USBF_VERBOSE_DEBUG ... +// +// Revision 1.3 2001/09/13 13:14:02 rudi +// +// Fixed a problem that would sometimes prevent the core to come out of +// reset and immediately be operational ... +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:51 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.2 2001/03/07 09:08:13 rudi +// +// Added USB control signaling (Line Status) block. Fixed some minor +// typos, added resume bit and signal. +// +// Revision 0.1.0.1 2001/02/28 08:11:07 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_pe( clk, rst, + + // UTMI Interfaces + tx_valid, rx_active, + + // PID Information + pid_OUT, pid_IN, pid_SOF, pid_SETUP, + pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, + pid_ACK, pid_NACK, pid_STALL, pid_NYET, + pid_PRE, pid_ERR, pid_SPLIT, pid_PING, + + // Speed Mode + mode_hs, + + // Token Information + token_valid, crc5_err, + + // Receive Data Output + rx_data_valid, rx_data_done, crc16_err, + + // Packet Assembler Interface + send_token, token_pid_sel, + data_pid_sel, send_zero_length, + + // IDMA Interface + rx_dma_en, tx_dma_en, + abort, idma_done, + adr, size, buf_size, + sizu_c, dma_en, + + // Register File Interface + fsel, idin, + dma_in_buf_sz1, dma_out_buf_avail, + ep_sel, match, nse_err, + buf0_rl, buf0_set, buf1_set, + uc_bsel_set, uc_dpd_set, + + int_buf1_set, int_buf0_set, int_upid_set, + int_crc16_set, int_to_set, int_seqerr_set, + out_to_small, + + csr, buf0, buf1 + + ); + +parameter SSRAM_HADR = 14; + +input clk, rst; +input tx_valid, rx_active; + +// Packet Disassembler Interface + // Decoded PIDs (used when token_valid is asserted) +input pid_OUT, pid_IN, pid_SOF, pid_SETUP; +input pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +input pid_ACK, pid_NACK, pid_STALL, pid_NYET; +input pid_PRE, pid_ERR, pid_SPLIT, pid_PING; + +input mode_hs; +input token_valid; // Token is valid +input crc5_err; // Token crc5 error + +input rx_data_valid; // Data on rx_data_st is valid +input rx_data_done; // Indicates end of a transfer +input crc16_err; // Data packet CRC 16 error + +// Packet Assembler Interface +output send_token; +output [1:0] token_pid_sel; +output [1:0] data_pid_sel; +output send_zero_length; + +// IDMA Interface +output rx_dma_en; // Allows the data to be stored +output tx_dma_en; // Allows for data to be retrieved +output abort; // Abort Transfer (time_out, crc_err or rx_error) +input idma_done; // DMA is done indicator +output [SSRAM_HADR + 2:0] adr; // Byte Address +output [13:0] size; // Size in bytes +output [13:0] buf_size; // Actual buffer size +input [10:0] sizu_c; // Up and Down counting size registers, used to update +output dma_en; // USB external DMA mode enabled + +// Register File interface +input fsel; // This function is selected +output [31:0] idin; // Data Output +input [3:0] ep_sel; // Endpoint Number Input +input match; // Endpoint Matched +output nse_err; // no such endpoint error +input dma_in_buf_sz1, dma_out_buf_avail; + +output buf0_rl; // Reload Buf 0 with original values +output buf0_set; // Write to buf 0 +output buf1_set; // Write to buf 1 +output uc_bsel_set; // Write to the uc_bsel field +output uc_dpd_set; // Write to the uc_dpd field +output int_buf1_set; // Set buf1 full/empty interrupt +output int_buf0_set; // Set buf0 full/empty interrupt +output int_upid_set; // Set unsupported PID interrupt +output int_crc16_set; // Set CRC16 error interrupt +output int_to_set; // Set time out interrupt +output int_seqerr_set; // Set PID sequence error interrupt +output out_to_small; // OUT packet was to small for DMA operation + +input [31:0] csr; // Internal CSR Output +input [31:0] buf0; // Internal Buf 0 Output +input [31:0] buf1; // Internal Buf 1 Output + + + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +// tx token decoding +parameter ACK = 0, + NACK = 1, + STALL = 2, + NYET = 3; + +// State decoding +parameter [9:0] // synopsys enum state + IDLE = 10'b000000_0001, + TOKEN = 10'b000000_0010, + IN = 10'b000000_0100, + IN2 = 10'b000000_1000, + OUT = 10'b000001_0000, + OUT2A = 10'b000010_0000, + OUT2B = 10'b000100_0000, + UPDATEW = 10'b001000_0000, + UPDATE = 10'b010000_0000, + UPDATE2 = 10'b100000_0000; + +reg [1:0] token_pid_sel; +reg [1:0] token_pid_sel_d; +reg send_token; +reg send_token_d; +reg rx_dma_en, tx_dma_en; +reg int_seqerr_set_d; +reg int_seqerr_set; +reg int_upid_set; + +reg match_r; + +// Endpoint Decoding +wire IN_ep, OUT_ep, CTRL_ep; // Endpoint Types +wire txfr_iso, txfr_bulk; // Transfer Types +wire ep_disabled, ep_stall; // Endpoint forced conditions + +wire lrg_ok, sml_ok; // Packet size acceptance +wire [1:0] tr_fr; // Number of transfers per micro-frame +wire [10:0] max_pl_sz; // Max payload size + +wire [1:0] uc_dpd, uc_bsel; + +// Buffer checks +wire buf_sel; +reg buf0_na, buf1_na; +wire [SSRAM_HADR + 2:0] buf0_adr, buf1_adr; +wire [13:0] buf0_sz, buf1_sz; +reg [9:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +// PID next and current decoders +reg [1:0] next_dpid; +reg [1:0] this_dpid; +reg pid_seq_err; +wire [1:0] tr_fr_d; + +wire [13:0] size_next; +wire buf_smaller; + +reg [SSRAM_HADR + 2:0] adr; +reg [13:0] new_size; +reg [13:0] new_sizeb; +reg buffer_full; +reg buffer_empty; +wire [SSRAM_HADR + 2:0] new_adr; +reg buffer_done; + +reg no_bufs0, no_bufs1; +wire no_bufs; + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has XXXnS to reply. +// "rx_ack_to" indicates when this time has expired. +// rx_ack_to_clr, clears the timer +reg rx_ack_to_clr; +reg rx_ack_to_clr_d; +reg rx_ack_to; +reg [7:0] rx_ack_to_cnt; + +// After sending a OUT token the host must send a data packet. +// The host has XX nS to send the packet. "tx_data_to" indicates +// when this time has expired. +// tx_data_to_clr, clears the timer +wire tx_data_to_clr; +reg tx_data_to; +reg [7:0] tx_data_to_cnt; + +wire [7:0] rx_ack_to_val, tx_data_to_val; + +reg int_set_en; + +wire [1:0] next_bsel; +reg buf_set_d; +reg uc_stat_set_d; +reg [31:0] idin; +reg buf0_set, buf1_set; +reg uc_bsel_set; +reg uc_dpd_set; +reg buf0_rl_d; +reg buf0_rl; +wire no_buf0_dma; +reg buf0_st_max; +reg buf1_st_max; + +reg [SSRAM_HADR + 2:0] adr_r; +reg [13:0] size_next_r; + +reg in_token; +reg out_token; +reg setup_token; + +wire in_op, out_op; // Indicate a IN or OUT operation +reg to_small; // Indicates a "to small packer" error +reg to_large; // Indicates a "to large packer" error + +reg buffer_overflow; +reg [1:0] allow_pid; + +reg nse_err; +reg out_to_small, out_to_small_r; +reg abort; + +reg buf0_not_aloc, buf1_not_aloc; + +reg send_zero_length; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// Endpoint/CSR Decoding +assign IN_ep = csr[27:26]==2'b01; +assign OUT_ep = csr[27:26]==2'b10; +assign CTRL_ep = csr[27:26]==2'b00; + +assign txfr_iso = csr[25:24]==2'b01; +assign txfr_bulk = csr[25:24]==2'b10; + +assign ep_disabled = csr[23:22]==2'b01; +assign ep_stall = csr[23:22]==2'b10; + +assign lrg_ok = csr[17]; +assign sml_ok = csr[16]; +assign dma_en = csr[15] & !CTRL_ep; + +assign tr_fr = csr[12:11]; +assign max_pl_sz = csr[10:0]; + +assign uc_dpd = csr[29:28]; +assign uc_bsel = csr[31:30]; + +// Buffer decoding and allocation checks +assign buf0_adr = buf0[SSRAM_HADR + 2:0]; +assign buf1_adr = buf1[SSRAM_HADR + 2:0]; +assign buf0_sz = buf0[30:17]; +assign buf1_sz = buf1[30:17]; + +// Buffers Not Available +always @(posedge clk) + buf0_na <= buf0[31] | ( &buf0_adr ); + +always @(posedge clk) + buf1_na <= buf1[31] | ( &buf1_adr ); + +// Buffer Not Allocated +always @(posedge clk) + buf0_not_aloc <= &buf0_adr; + +always @(posedge clk) + buf1_not_aloc <= &buf1_adr; + +always @(posedge clk) + match_r <= match; + +// No Such Endpoint Indicator +always @(posedge clk) + nse_err <= token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match; + +always @(posedge clk) + send_token <= send_token_d; + +always @(posedge clk) + token_pid_sel <= token_pid_sel_d; + +/////////////////////////////////////////////////////////////////// +// +// Data Pid Sequencer +// + +assign tr_fr_d = mode_hs ? tr_fr : 2'h0; + +always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd + casex({tr_fr_d,csr[27:26],csr[25:24],uc_dpd}) // synopsys full_case parallel_case + 8'b0?_01_01_??: next_dpid <= 2'b00; // ISO txfr. IN, 1 tr/mf + + 8'b10_01_01_?0: next_dpid <= 2'b01; // ISO txfr. IN, 2 tr/mf + 8'b10_01_01_?1: next_dpid <= 2'b00; // ISO txfr. IN, 2 tr/mf + + 8'b11_01_01_00: next_dpid <= 2'b01; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_01: next_dpid <= 2'b10; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_10: next_dpid <= 2'b00; // ISO txfr. IN, 3 tr/mf + + 8'b0?_10_01_??: next_dpid <= 2'b00; // ISO txfr. OUT, 1 tr/mf + + 8'b10_10_01_??: // ISO txfr. OUT, 2 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA1}) // synopsys full_case parallel_case + 2'b10: next_dpid <= 2'b01; + 2'b01: next_dpid <= 2'b00; + endcase + end + + 8'b11_10_01_00: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= 2'b01; + 2'b01: next_dpid <= 2'b00; + endcase + end + 8'b11_10_01_01: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= 2'b10; + 2'b01: next_dpid <= 2'b00; + endcase + end + 8'b11_10_01_10: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= 2'b01; + 2'b01: next_dpid <= 2'b00; + endcase + end + + 8'b??_01_00_?0, // IN/OUT endpoint only + 8'b??_10_00_?0: next_dpid <= 2'b01; // INT transfers + + 8'b??_01_00_?1, // IN/OUT endpoint only + 8'b??_10_00_?1: next_dpid <= 2'b00; // INT transfers + + 8'b??_01_10_?0, // IN/OUT endpoint only + 8'b??_10_10_?0: next_dpid <= 2'b01; // BULK transfers + + 8'b??_01_10_?1, // IN/OUT endpoint only + 8'b??_10_10_?1: next_dpid <= 2'b00; // BULK transfers + + 8'b??_00_??_??: // CTRL Endpoint + casex({setup_token, in_op, out_op, uc_dpd}) // synopsys full_case parallel_case + 5'b1_??_??: next_dpid <= 2'b11; // SETUP operation + 5'b0_10_0?: next_dpid <= 2'b11; // IN operation + 5'b0_10_1?: next_dpid <= 2'b01; // IN operation + 5'b0_01_?0: next_dpid <= 2'b11; // OUT operation + 5'b0_01_?1: next_dpid <= 2'b10; // OUT operation + endcase + + endcase + +// Current PID decoder + +// Allow any PID for ISO. transfers when mode full speed or tr_fr is zero +always @(pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA) + case({pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA} ) // synopsys full_case parallel_case + 4'b1000: allow_pid = 2'b00; + 4'b0100: allow_pid = 2'b01; + 4'b0010: allow_pid = 2'b10; + 4'b0001: allow_pid = 2'b11; + endcase + +always @(posedge clk) // tf/mf:ep/type:tr/type:last dpd + casex({tr_fr_d,csr[27:26],csr[25:24],uc_dpd}) // synopsys full_case parallel_case + 8'b0?_01_01_??: this_dpid <= 2'b00; // ISO txfr. IN, 1 tr/mf + + 8'b10_01_01_?0: this_dpid <= 2'b01; // ISO txfr. IN, 2 tr/mf + 8'b10_01_01_?1: this_dpid <= 2'b00; // ISO txfr. IN, 2 tr/mf + + 8'b11_01_01_00: this_dpid <= 2'b10; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_01: this_dpid <= 2'b01; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_10: this_dpid <= 2'b00; // ISO txfr. IN, 3 tr/mf + + 8'b00_10_01_??: this_dpid <= allow_pid; // ISO txfr. OUT, 0 tr/mf + 8'b01_10_01_??: this_dpid <= 2'b00; // ISO txfr. OUT, 1 tr/mf + + 8'b10_10_01_?0: this_dpid <= 2'b11; // ISO txfr. OUT, 2 tr/mf + 8'b10_10_01_?1: this_dpid <= 2'b01; // ISO txfr. OUT, 2 tr/mf + + 8'b11_10_01_00: this_dpid <= 2'b11; // ISO txfr. OUT, 3 tr/mf + 8'b11_10_01_01: this_dpid <= 2'b11; // ISO txfr. OUT, 3 tr/mf + 8'b11_10_01_10: this_dpid <= 2'b10; // ISO txfr. OUT, 3 tr/mf + + 8'b??_01_00_?0, // IN/OUT endpoint only + 8'b??_10_00_?0: this_dpid <= 2'b00; // INT transfers + 8'b??_01_00_?1, // IN/OUT endpoint only + 8'b??_10_00_?1: this_dpid <= 2'b01; // INT transfers + + 8'b??_01_10_?0, // IN/OUT endpoint only + 8'b??_10_10_?0: this_dpid <= 2'b00; // BULK transfers + 8'b??_01_10_?1, // IN/OUT endpoint only + 8'b??_10_10_?1: this_dpid <= 2'b01; // BULK transfers + + 8'b??_00_??_??: // CTRL Endpoint + casex({setup_token,in_op, out_op, uc_dpd}) // synopsys full_case parallel_case + 5'b1_??_??: this_dpid <= 2'b00; // SETUP operation + 5'b0_10_0?: this_dpid <= 2'b00; // IN operation + 5'b0_10_1?: this_dpid <= 2'b01; // IN operation + 5'b0_01_?0: this_dpid <= 2'b00; // OUT operation + 5'b0_01_?1: this_dpid <= 2'b01; // OUT operation + endcase + endcase + +// Assign PID for outgoing packets +assign data_pid_sel = this_dpid; + +// Verify PID for incoming data packets +always @(posedge clk) + pid_seq_err <= !( (this_dpid==2'b00 & pid_DATA0) | + (this_dpid==2'b01 & pid_DATA1) | + (this_dpid==2'b10 & pid_DATA2) | + (this_dpid==2'b11 & pid_MDATA) ); + +/////////////////////////////////////////////////////////////////// +// +// IDMA Setup & src/dst buffer select +// + +// For Control endpoints things are different: +// buffer0 is used for OUT (incoming) data packets +// buffer1 is used for IN (outgoing) data packets + +// Keep track of last token for control endpoints +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) in_token <= 1'b0; + else + if(pid_IN) in_token <= 1'b1; + else + if(pid_OUT || pid_SETUP) in_token <= 1'b0; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) out_token <= 1'b0; + else + if(pid_OUT || pid_SETUP) out_token <= 1'b1; + else + if(pid_IN) out_token <= 1'b0; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) setup_token <= 1'b0; + else + if(pid_SETUP) setup_token <= 1'b1; + else + if(pid_OUT || pid_IN) setup_token <= 1'b0; + +// Indicates if we are performing an IN operation +assign in_op = IN_ep | (CTRL_ep & in_token); + +// Indicates if we are performing an OUT operation +assign out_op = OUT_ep | (CTRL_ep & out_token); + +// Select buffer: buf_sel==0 buffer0; buf_sel==1 buffer1 +assign buf_sel = dma_en ? 1'b0 : CTRL_ep ? in_token : ((uc_bsel[0] | buf0_na) & !buf1_na); + +// Select Address for IDMA +always @(posedge clk) + adr <= buf_sel ? buf1_adr : buf0_adr; + +// Size from Buffer +assign buf_size = buf_sel ? buf1_sz : buf0_sz; + +// Determine which is smaller: buffer or max_pl_sz +assign buf_smaller = buf_size < {3'h0, max_pl_sz}; + +// Determine actual size for this transfer (for IDMA) IN endpoint only +// (OUT endpoint uses sizeu_c from IDMA) +assign size_next = buf_smaller ? buf_size : max_pl_sz; +assign size = size_next; // "size" is an output for IDMA + +// Buffer Full (only for OUT endpoints) +// Indicates that there is not enough space in the buffer for one +// more max_pl_sz packet +always @(posedge clk) + buffer_full <= new_size < {3'h0, max_pl_sz}; + +// Buffer Empty (only for IN endpoints) +// Indicates that there are zero bytes left in the buffer +always @(posedge clk) + buffer_empty <= (new_size == 14'h0); + +// Joint buffer full/empty flag This is the "USED" flag +always @(posedge clk) + buffer_done <= in_op ? buffer_empty : buffer_full; + +// No More buffer space at all (For high speed out - issue NYET) +assign no_buf0_dma = dma_en & + ((IN_ep & !dma_in_buf_sz1) | (OUT_ep & !dma_out_buf_avail)); + +always @(posedge clk) + buf0_st_max <= (buf0_sz < {3'h0, max_pl_sz}); + +always @(posedge clk) + buf1_st_max <= (buf1_sz < {3'h0, max_pl_sz}); + +always @(posedge clk) + no_bufs0 <= buf0_na | no_buf0_dma | + (buf_sel ? buf0_st_max : (buffer_full & !dma_en)); + +always @(posedge clk) + no_bufs1 <= buf1_na | (buf_sel ? buffer_full : buf1_st_max); + +assign no_bufs = no_bufs0 & no_bufs1; + +// New Size (to be written to register file) +always @(posedge clk) + new_sizeb <= (out_op && dma_en) ? max_pl_sz : (in_op ? size_next : sizu_c); + +always @(posedge clk) + new_size <= buf_size - new_sizeb; + + +// New Buffer Address (to be written to register file) +always @(posedge clk) + adr_r <= adr; + +always @(posedge clk) + size_next_r <= size_next; + +assign new_adr = adr_r[SSRAM_HADR + 2:0] + + ((out_op && dma_en) ? {{SSRAM_HADR + 2-10{1'b0}}, max_pl_sz[10:0]} : + (in_op ? {{SSRAM_HADR + 2-13{1'b0}}, size_next_r[13:0] } : + { {SSRAM_HADR + 2-10{1'b0}}, sizu_c[10:0]})); + +// Buffer Overflow +always @(posedge clk) + buffer_overflow <= ( {3'h0, sizu_c} > buf_size) & rx_data_valid; + + +// OUT packet smaller than MAX_PL_SZ in DMA operation +always @(posedge clk) + out_to_small_r <= uc_stat_set_d & out_op & dma_en & (sizu_c != max_pl_sz); + +always @(posedge clk) + out_to_small <= out_to_small_r; + +/////////////////////////////////////////////////////////////////// +// +// Determine if packet is to small or to large +// This is used to NACK and ignore packet for OUT endpoints +// + +always @(posedge clk) + to_small <= !sml_ok & (sizu_c < max_pl_sz); + +always @(posedge clk) + to_large <= !lrg_ok & (sizu_c > max_pl_sz); + +/////////////////////////////////////////////////////////////////// +// +// Register File Update Logic +// + +assign next_bsel = dma_en ? 2'h0 : buffer_done ? uc_bsel + 2'h1 : uc_bsel; // FIX_ME + +always @(posedge clk) + idin[31:17] <= out_to_small_r ? {4'h0,sizu_c} : {buffer_done,new_size}; + +always @(posedge clk) + idin[SSRAM_HADR + 2:4] <= out_to_small_r ? buf0_adr[SSRAM_HADR + 2:4] : + new_adr[SSRAM_HADR + 2:4]; + +always @(posedge clk) + if(buf_set_d) idin[3:0] <= new_adr[3:0]; + else + if(out_to_small_r) idin[3:0] <= buf0_adr[3:0]; + else idin[3:0] <= {next_dpid, next_bsel}; + +always @(posedge clk) + buf0_set <= !buf_sel & buf_set_d; + +always @(posedge clk) + buf1_set <= buf_sel & buf_set_d; + +always @(posedge clk) + uc_bsel_set <= uc_stat_set_d; + +always @(posedge clk) + uc_dpd_set <= uc_stat_set_d; + +always @(posedge clk) + buf0_rl <= buf0_rl_d; + +// Abort signal +always @(posedge clk) + abort <= buffer_overflow | (match & (state != IDLE) ) | (match_r & to_large); + +/////////////////////////////////////////////////////////////////// +// +// TIME OUT TIMERS +// + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has 622nS in Full Speed +// mode and 400nS in High Speed mode to reply. +// "rx_ack_to" indicates when this time has expired. +// rx_ack_to_clr, clears the timer + +always @(posedge clk) + rx_ack_to_clr <= tx_valid | rx_ack_to_clr_d; + +always @(posedge clk) + if(rx_ack_to_clr) rx_ack_to_cnt <= 8'h0; + else rx_ack_to_cnt <= rx_ack_to_cnt + 8'h1; + +always @(posedge clk) + rx_ack_to <= (rx_ack_to_cnt == rx_ack_to_val); + +assign rx_ack_to_val = mode_hs ? `USBF_RX_ACK_TO_VAL_HS : `USBF_RX_ACK_TO_VAL_FS; + +// After sending a OUT token the host must send a data packet. +// The host has 622nS in Full Speed mode and 400nS in High Speed +// mode to send the data packet. +// "tx_data_to" indicates when this time has expired. +// "tx_data_to_clr" clears the timer + +assign tx_data_to_clr = rx_active; + +always @(posedge clk) + if(tx_data_to_clr) tx_data_to_cnt <= 8'h0; + else tx_data_to_cnt <= tx_data_to_cnt + 8'h1; + +always @(posedge clk) + tx_data_to <= (tx_data_to_cnt == tx_data_to_val); + +assign tx_data_to_val = mode_hs ? `USBF_TX_DATA_TO_VAL_HS : `USBF_TX_DATA_TO_VAL_FS; + +/////////////////////////////////////////////////////////////////// +// +// Interrupts +// +reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r; + +assign int_buf1_set = !buf_sel & buffer_done & int_set_en & !buf1_not_aloc; +assign int_buf0_set = buf_sel & buffer_done & int_set_en & !buf0_not_aloc; + +always @(posedge clk) + pid_OUT_r <= pid_OUT; + +always @(posedge clk) + pid_IN_r <= pid_IN; + +always @(posedge clk) + pid_PING_r <= pid_PING; + +always @(posedge clk) + pid_SETUP_r <= pid_SETUP; + +always @(posedge clk) + int_upid_set <= match_r & !pid_SOF & ( + ( OUT_ep & !(pid_OUT_r | pid_PING_r)) | + ( IN_ep & !pid_IN_r) | + (CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) + ); + +assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to); + +assign int_crc16_set = rx_data_done & crc16_err; + +always @(posedge clk) + int_seqerr_set <= int_seqerr_set_d; + +/////////////////////////////////////////////////////////////////// +// +// Main Protocol State Machine +// + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else + if(match) state <= IDLE; + else state <= next_state; + +always @(state or ep_stall or buf0_na or buf1_na or + pid_seq_err or idma_done or token_valid or pid_ACK or rx_data_done or + tx_data_to or crc16_err or ep_disabled or no_bufs or mode_hs + or dma_en or rx_ack_to or pid_PING or txfr_iso or to_small or to_large or + CTRL_ep or pid_IN or pid_OUT or IN_ep or OUT_ep or pid_SETUP or pid_SOF + or match_r or abort or buffer_done or no_buf0_dma or max_pl_sz) + begin + next_state = state; + token_pid_sel_d = ACK; + send_token_d = 1'b0; + rx_dma_en = 1'b0; + tx_dma_en = 1'b0; + buf_set_d = 1'b0; + uc_stat_set_d = 1'b0; + buf0_rl_d = 1'b0; + int_set_en = 1'b0; + rx_ack_to_clr_d = 1'b1; + int_seqerr_set_d = 1'b0; + send_zero_length = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IDLE (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(rst && match_r && !ep_disabled && !pid_SOF) + begin + if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); + if(ep_disabled === 1'bx)$display("ERROR: IDLE: ep_disabled is unknown. (%t)", $time); + if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); + if(ep_stall === 1'bx) $display("ERROR: IDLE: ep_stall is unknown. (%t)", $time); + if(buf0_na === 1'bx) $display("ERROR: IDLE: buf0_na is unknown. (%t)", $time); + if(buf1_na === 1'bx) $display("ERROR: IDLE: buf1_na is unknown. (%t)", $time); + if(no_buf0_dma === 1'bx)$display("ERROR: IDLE: no_buf0_dma is unknown. (%t)", $time); + if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); + if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); + if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); + if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); + if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); + if(mode_hs === 1'bx) $display("ERROR: IDLE: mode_hs is unknown. (%t)", $time); + if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); + if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); + end +`endif +// synopsys translate_on + + if(match_r && !ep_disabled && !pid_SOF) + begin + if(ep_stall) // Halt Forced send STALL + begin + token_pid_sel_d = STALL; + send_token_d = 1'b1; + next_state = TOKEN; + end + else + if( (buf0_na && buf1_na) || no_buf0_dma || + (CTRL_ep && pid_IN && buf1_na) || + (CTRL_ep && pid_OUT && buf0_na) + ) + begin // No buffers send NAK + token_pid_sel_d = NACK; + send_token_d = 1'b1; + next_state = TOKEN; + end + else + if(pid_PING && mode_hs) + begin + token_pid_sel_d = ACK; + send_token_d = 1'b1; + next_state = TOKEN; + end + else + if(IN_ep || (CTRL_ep && pid_IN)) + begin + if(max_pl_sz == 11'h0) send_zero_length = 1'b1; + tx_dma_en = 1'b1; + next_state = IN; + end + else + if(OUT_ep || (CTRL_ep && (pid_OUT || pid_SETUP))) + begin + rx_dma_en = 1'b1; + next_state = OUT; + end + end + end + + TOKEN: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state TOKEN (%t)", $time); +`endif +// synopsys translate_on + next_state = IDLE; + end + + IN: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IN (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); + if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time); +`endif +// synopsys translate_on + rx_ack_to_clr_d = 1'b0; + if(idma_done) + begin + if(txfr_iso) next_state = UPDATE; + else next_state = IN2; + end + + end + IN2: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IN2 (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); + if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); + if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time); +`endif +// synopsys translate_on + rx_ack_to_clr_d = 1'b0; + // Wait for ACK from HOST or Timeout + if(rx_ack_to) next_state = IDLE; + else + if(token_valid && pid_ACK) + begin + next_state = UPDATE; + end + end + + OUT: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); + if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); + if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); + if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); + if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); + if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(tx_data_to || crc16_err || abort ) + next_state = IDLE; + else + if(rx_data_done) + begin // Send Ack + if(txfr_iso) + begin + if(pid_seq_err) int_seqerr_set_d = 1'b1; + next_state = UPDATEW; + end + else next_state = OUT2A; + end + end + + OUT2A: + begin // This is a delay State to NACK to small or to + // large packets. this state could be skipped +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT2A (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(abort) next_state = IDLE; + else next_state = OUT2B; + end + OUT2B: + begin // Send ACK/NACK/NYET +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT2B (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(abort === 1'bx) $display("ERROR: OUT2B: abort is unknown. (%t)", $time); + if(to_small === 1'bx) $display("ERROR: OUT2B: to_small is unknown. (%t)", $time); + if(to_large === 1'bx) $display("ERROR: OUT2B: to_large is unknown. (%t)", $time); + if(pid_seq_err === 1'bx)$display("ERROR: OUT2B: rx_data_done is unknown. (%t)", $time); + if(mode_hs === 1'bx) $display("ERROR: OUT2B: mode_hs is unknown. (%t)", $time); + if(no_bufs === 1'bx) $display("ERROR: OUT2B: no_bufs is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(abort) next_state = IDLE; + else + if(to_small || to_large) + begin + token_pid_sel_d = NACK; + next_state = IDLE; + end + else + if(pid_seq_err) + begin + token_pid_sel_d = ACK; + send_token_d = 1'b1; + next_state = IDLE; + end + else + begin + if(mode_hs && no_bufs) token_pid_sel_d = NYET; + else token_pid_sel_d = ACK; + send_token_d = 1'b1; + next_state = UPDATE; + end + end + + UPDATEW: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state UPDATEW (%t)", $time); +`endif +// synopsys translate_on + next_state = UPDATE; + end + UPDATE: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state UPDATE (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(buffer_done === 1'bx) $display("ERROR: UPDATE: buffer_done is unknown. (%t)", $time); + if(dma_en === 1'bx) $display("ERROR: UPDATE: dma_en is unknown. (%t)", $time); +`endif +// synopsys translate_on + // Interrupts + int_set_en = 1'b1; + // Buffer (used, size, adr) set or reload + if(buffer_done && dma_en) + begin + buf0_rl_d = 1'b1; + end + else + begin + buf_set_d = 1'b1; + end + next_state = UPDATE2; + end + UPDATE2: // Update Register File & state + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state UPDATE2 (%t)", $time); +`endif +// synopsys translate_on + // pid sequence & buffer usage + uc_stat_set_d = 1'b1; + next_state = IDLE; + end + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v new file mode 100644 index 000000000..ff8b4bbe6 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v @@ -0,0 +1,483 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Protocol Layer //// +//// This block is typically referred to as the SEI in USB //// +//// Specification. It encapsulates the Packet Assembler, //// +//// disassembler, protocol engine and internal DMA //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_pl.v,v 1.5 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_pl.v,v $ +// Revision 1.5 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.4 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.3 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:52 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:11:11 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_pl( clk, rst, + + // UTMI Interface + rx_data, rx_valid, rx_active, rx_err, + tx_data, tx_valid, tx_valid_last, tx_ready, + tx_first, tx_valid_out, + mode_hs, usb_reset, usb_suspend, usb_attached, + + // memory interface + madr, mdout, mdin, mwe, mreq, mack, + + // Register File Interface + fa, idin, + ep_sel, match, + dma_in_buf_sz1, dma_out_buf_avail, + buf0_rl, buf0_set, buf1_set, + uc_bsel_set, uc_dpd_set, + + int_buf1_set, int_buf0_set, int_upid_set, + int_crc16_set, int_to_set, int_seqerr_set, + out_to_small, csr, buf0, buf1, + + // Misc + frm_nat, + pid_cs_err, nse_err, + crc5_err + ); + +parameter SSRAM_HADR = 14; + +// UTMI Interface +input clk, rst; +input [7:0] rx_data; +input rx_valid, rx_active, rx_err; +output [7:0] tx_data; +output tx_valid; +output tx_valid_last; +input tx_ready; +output tx_first; +input tx_valid_out; +input mode_hs; // High Speed Mode +input usb_reset; // USB Reset +input usb_suspend; // USB Suspend +input usb_attached; // Attached to USB + +// Memory Arbiter Interface +output [SSRAM_HADR:0] madr; // word address +output [31:0] mdout; +input [31:0] mdin; +output mwe; +output mreq; +input mack; + +// Register File interface +input [6:0] fa; // Function Address (as set by the controller) +output [31:0] idin; // Data Input +output [3:0] ep_sel; // Endpoint Number Input +input match; // Endpoint Matched +input dma_in_buf_sz1; +input dma_out_buf_avail; +output nse_err; // no such endpoint error + +output buf0_rl; // Reload Buf 0 with original values +output buf0_set; // Write to buf 0 +output buf1_set; // Write to buf 1 +output uc_bsel_set; // Write to the uc_bsel field +output uc_dpd_set; // Write to the uc_dpd field +output int_buf1_set; // Set buf1 full/empty interrupt +output int_buf0_set; // Set buf0 full/empty interrupt +output int_upid_set; // Set unsupported PID interrupt +output int_crc16_set; // Set CRC16 error interrupt +output int_to_set; // Set time out interrupt +output int_seqerr_set; // Set PID sequence error interrupt +output out_to_small; // OUT packet was to small for DMA operation + +input [31:0] csr; // Internal CSR Output +input [31:0] buf0; // Internal Buf 0 Output +input [31:0] buf1; // Internal Buf 1 Output + +// Misc +output pid_cs_err; // pid checksum error +output crc5_err; // crc5 error +output [31:0] frm_nat; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +// Packet Disassembler Interface +wire clk, rst; +wire [7:0] rx_data; +wire pid_OUT, pid_IN, pid_SOF, pid_SETUP; +wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +wire pid_ACK, pid_NACK, pid_STALL, pid_NYET; +wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING; +wire [6:0] token_fadr; +wire token_valid; +wire crc5_err; +wire [10:0] frame_no; +wire [7:0] rx_data_st; +wire rx_data_valid; +wire rx_data_done; +wire crc16_err; +wire rx_seq_err; + +// Packet Assembler Interface +wire send_token; +wire [1:0] token_pid_sel; +wire send_data; +wire [1:0] data_pid_sel; +wire [7:0] tx_data_st; +wire rd_next; + +// IDMA Interface +wire rx_dma_en; // Allows the data to be stored +wire tx_dma_en; // Allows for data to be retrieved +wire abort; // Abort Transfer (time_out, crc_err or rx_error) +wire idma_done; // DMA is done +wire [SSRAM_HADR + 2:0] adr; // Byte Address +wire [13:0] size; // Size in bytes +wire [10:0] sizu_c; // Up and Down counting size registers, used + // to update +wire [13:0] buf_size; // Actual buffer size +wire dma_en; // external dma enabled + +// Memory Arbiter Interface +wire [SSRAM_HADR:0] madr; // word address +wire [31:0] mdout; +wire [31:0] mdin; +wire mwe; +wire mreq; +wire mack; + +// Local signals +wire pid_bad, pid_bad1, pid_bad2; + +reg hms_clk; // 0.5 Micro Second Clock +reg [4:0] hms_cnt; +reg [10:0] frame_no_r; // Current Frame Number register +wire frame_no_we; +reg frame_no_same; // Indicates current and prev. frame numbers + // are equal +reg [3:0] mfm_cnt; // Micro Frame Counter +reg [11:0] sof_time; // Time since last sof +reg clr_sof_time; +wire fsel; // This Function is selected +wire match_o; + +reg frame_no_we_r; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// PIDs we should never receive +assign pid_bad1 = pid_ACK | pid_NACK | pid_STALL | pid_NYET | pid_PRE | + pid_ERR | pid_SPLIT; + +// PIDs we should never get in full speed mode (high speed mode only) +assign pid_bad2 = !mode_hs & pid_PING; + +// All bad pids +assign pid_bad = pid_bad1 | pid_bad2; + +assign match_o = !pid_bad & fsel & match & token_valid & !crc5_err; + +// Frame Number (from SOF token) +assign frame_no_we = token_valid & !crc5_err & pid_SOF; + +always @(posedge clk) + frame_no_we_r <= frame_no_we; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) frame_no_r <= 11'h0; + else + if(frame_no_we_r) frame_no_r <= frame_no; + +// Micro Frame Counter +always @(posedge clk) + frame_no_same <= frame_no_we & (frame_no_r == frame_no); + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) mfm_cnt <= 4'h0; + else + if(frame_no_we_r && !frame_no_same) + mfm_cnt <= 4'h0; + else + if(frame_no_same) mfm_cnt <= mfm_cnt + 4'h1; + +//SOF delay counter +always @(posedge clk) + clr_sof_time <= frame_no_we; + +always @(posedge clk) + if(clr_sof_time) sof_time <= 12'h0; + else + if(hms_clk) sof_time <= sof_time + 12'h1; + +assign frm_nat = {mfm_cnt, 1'b0, frame_no_r, 4'h0, sof_time}; + +// 0.5 Micro Seconds Clock Generator +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) hms_cnt <= 5'h0; + else + if(hms_clk || frame_no_we_r) hms_cnt <= 5'h0; + else hms_cnt <= hms_cnt + 5'h1; + +always @(posedge clk) + hms_clk <= (hms_cnt == `USBF_HMS_DEL); + +/////////////////////////////////////////////////////////////////// + +// This function is addressed +assign fsel = (token_fadr == fa); + +/////////////////////////////////////////////////////////////////// +// +// Module Instantiations +// + +//Packet Decoder +usbf_pd u0( .clk( clk ), + .rst( rst ), + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + .pid_OUT( pid_OUT ), + .pid_IN( pid_IN ), + .pid_SOF( pid_SOF ), + .pid_SETUP( pid_SETUP ), + .pid_DATA0( pid_DATA0 ), + .pid_DATA1( pid_DATA1 ), + .pid_DATA2( pid_DATA2 ), + .pid_MDATA( pid_MDATA ), + .pid_ACK( pid_ACK ), + .pid_NACK( pid_NACK ), + .pid_STALL( pid_STALL ), + .pid_NYET( pid_NYET ), + .pid_PRE( pid_PRE ), + .pid_ERR( pid_ERR ), + .pid_SPLIT( pid_SPLIT ), + .pid_PING( pid_PING ), + .pid_cks_err( pid_cs_err ), + .token_fadr( token_fadr ), + .token_endp( ep_sel ), + .token_valid( token_valid ), + .crc5_err( crc5_err ), + .frame_no( frame_no ), + .rx_data_st( rx_data_st ), + .rx_data_valid( rx_data_valid ), + .rx_data_done( rx_data_done ), + .crc16_err( crc16_err ), + .seq_err( rx_seq_err ) + ); + +// Packet Assembler +usbf_pa u1( .clk( clk ), + .rst( rst ), + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ), + .send_token( send_token ), + .token_pid_sel( token_pid_sel ), + .send_data( send_data ), + .data_pid_sel( data_pid_sel ), + .send_zero_length( send_zero_length ), + .tx_data_st( tx_data_st ), + .rd_next( rd_next ) + ); + +// Internal DMA / Memory Arbiter Interface +usbf_idma #(SSRAM_HADR) + u2( .clk( clk ), + .rst( rst ), + .rx_data_st( rx_data_st ), + .rx_data_valid( rx_data_valid ), + .rx_data_done( rx_data_done ), + .send_data( send_data ), + .tx_data_st( tx_data_st ), + .rd_next( rd_next ), + .rx_dma_en( rx_dma_en ), + .tx_dma_en( tx_dma_en ), + .abort( abort ), + .idma_done( idma_done ), + .adr( adr ), + .size( size ), + .buf_size( buf_size ), + .dma_en( dma_en ), + .send_zero_length( send_zero_length ), + .madr( madr ), + .sizu_c( sizu_c ), + .mdout( mdout ), + .mdin( mdin ), + .mwe( mwe ), + .mreq( mreq ), + .mack( mack ) + ); + +// Protocol Engine +usbf_pe #(SSRAM_HADR) + u3( .clk( clk ), + .rst( rst ), + .tx_valid( tx_valid_out ), + .rx_active( rx_active ), + .pid_OUT( pid_OUT ), + .pid_IN( pid_IN ), + .pid_SOF( pid_SOF ), + .pid_SETUP( pid_SETUP ), + .pid_DATA0( pid_DATA0 ), + .pid_DATA1( pid_DATA1 ), + .pid_DATA2( pid_DATA2 ), + .pid_MDATA( pid_MDATA ), + .pid_ACK( pid_ACK ), + .pid_NACK( pid_NACK ), + .pid_STALL( pid_STALL ), + .pid_NYET( pid_NYET ), + .pid_PRE( pid_PRE ), + .pid_ERR( pid_ERR ), + .pid_SPLIT( pid_SPLIT ), + .pid_PING( pid_PING ), + .mode_hs( mode_hs ), + .token_valid( token_valid ), + .crc5_err( crc5_err ), + .rx_data_valid( rx_data_valid ), + .rx_data_done( rx_data_done ), + .crc16_err( crc16_err ), + .send_token( send_token ), + .token_pid_sel( token_pid_sel ), + .data_pid_sel( data_pid_sel ), + .send_zero_length( send_zero_length ), + .rx_dma_en( rx_dma_en ), + .tx_dma_en( tx_dma_en ), + .abort( abort ), + .idma_done( idma_done ), + .adr( adr ), + .size( size ), + .buf_size( buf_size ), + .sizu_c( sizu_c ), + .dma_en( dma_en ), + .fsel( fsel ), + .idin( idin ), + .ep_sel( ep_sel ), + .match( match_o ), + .dma_in_buf_sz1( dma_in_buf_sz1 ), + .dma_out_buf_avail( dma_out_buf_avail ), + .nse_err( nse_err ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( csr ), + .buf0( buf0 ), + .buf1( buf1 ) + ); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v new file mode 100644 index 000000000..54c85a500 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v @@ -0,0 +1,1909 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Register File //// +//// This module contains all top level registers and //// +//// instantiates the register files for endpoints //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_rf.v,v 1.6 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.6 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_rf.v,v $ +// Revision 1.6 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.5 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.4 2001/11/03 03:26:23 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.3 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:52 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.2 2001/03/07 09:08:13 rudi +// +// Added USB controll signaling (Line Status) block. Fixed some minor +// typos, added resume bit and signal. +// +// Revision 0.1.0.1 2001/02/28 08:11:32 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +// Endpoint register File +module usbf_rf( clk, wclk, rst, + + // Wishbone Interface + adr, re, we, din, dout, inta, intb, + dma_req, dma_ack, + + // Internal Interface + idin, + ep_sel, match, + buf0_rl, buf0_set, buf1_set, + uc_bsel_set, uc_dpd_set, + + int_buf1_set, int_buf0_set, int_upid_set, + int_crc16_set, int_to_set, int_seqerr_set, + out_to_small, + + csr, buf0, buf1, + funct_adr, + dma_in_buf_sz1, dma_out_buf_avail, + + // Misc + frm_nat, + utmi_vend_stat, utmi_vend_ctrl, utmi_vend_wr, + line_stat, usb_attached, mode_hs, suspend, + attached, usb_reset, pid_cs_err, nse_err, + crc5_err, rx_err, rf_resume_req + ); + +input clk, wclk, rst; +input [6:0] adr; +input re; +input we; +input [31:0] din; +output [31:0] dout; +output inta, intb; +output [15:0] dma_req; +input [15:0] dma_ack; + +input [31:0] idin; // Data Input +input [3:0] ep_sel; // Endpoint Number Input +output match; // Endpoint Matched +input buf0_rl; // Reload Buf 0 with original values + +input buf0_set; // Write to buf 0 +input buf1_set; // Write to buf 1 +input uc_bsel_set; // Write to the uc_bsel field +input uc_dpd_set; // Write to the uc_dpd field +input int_buf1_set; // Set buf1 full/empty interrupt +input int_buf0_set; // Set buf0 full/empty interrupt +input int_upid_set; // Set unsupported PID interrupt +input int_crc16_set; // Set CRC16 error interrupt +input int_to_set; // Set time out interrupt +input int_seqerr_set; // Set PID Sequence Error Interrupt +input out_to_small; // OUT packet was to small for DMA operation + +output [31:0] csr; // Internal CSR Output +output [31:0] buf0; // Internal Buf 0 Output +output [31:0] buf1; // Internal Buf 1 Output +output [6:0] funct_adr; // Function Address +output dma_in_buf_sz1, dma_out_buf_avail; + +input [31:0] frm_nat; + +input [7:0] utmi_vend_stat; // UTMI Vendor C/S bus +output [3:0] utmi_vend_ctrl; +output utmi_vend_wr; + +input [1:0] line_stat; // Below are signals for interrupt generation +input usb_attached; +input mode_hs; +input suspend; +input attached; +input usb_reset; +input nse_err; +input pid_cs_err; +input crc5_err; +input rx_err; +output rf_resume_req; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +wire [31:0] ep0_dout, ep1_dout, ep2_dout, ep3_dout; +wire [31:0] ep4_dout, ep5_dout, ep6_dout, ep7_dout; +wire [31:0] ep8_dout, ep9_dout, ep10_dout, ep11_dout; +wire [31:0] ep12_dout, ep13_dout, ep14_dout, ep15_dout; + +wire ep0_re, ep1_re, ep2_re, ep3_re; +wire ep4_re, ep5_re, ep6_re, ep7_re; +wire ep8_re, ep9_re, ep10_re, ep11_re; +wire ep12_re, ep13_re, ep14_re, ep15_re; + +wire ep0_we, ep1_we, ep2_we, ep3_we; +wire ep4_we, ep5_we, ep6_we, ep7_we; +wire ep8_we, ep9_we, ep10_we, ep11_we; +wire ep12_we, ep13_we, ep14_we, ep15_we; + +wire ep0_inta, ep1_inta, ep2_inta, ep3_inta; +wire ep4_inta, ep5_inta, ep6_inta, ep7_inta; +wire ep8_inta, ep9_inta, ep10_inta, ep11_inta; +wire ep12_inta, ep13_inta, ep14_inta, ep15_inta; + +wire ep0_intb, ep1_intb, ep2_intb, ep3_intb; +wire ep4_intb, ep5_intb, ep6_intb, ep7_intb; +wire ep8_intb, ep9_intb, ep10_intb, ep11_intb; +wire ep12_intb, ep13_intb, ep14_intb, ep15_intb; + +wire ep0_match, ep1_match, ep2_match, ep3_match; +wire ep4_match, ep5_match, ep6_match, ep7_match; +wire ep8_match, ep9_match, ep10_match, ep11_match; +wire ep12_match, ep13_match, ep14_match, ep15_match; + +wire [31:0] ep0_csr, ep1_csr, ep2_csr, ep3_csr; +wire [31:0] ep4_csr, ep5_csr, ep6_csr, ep7_csr; +wire [31:0] ep8_csr, ep9_csr, ep10_csr, ep11_csr; +wire [31:0] ep12_csr, ep13_csr, ep14_csr, ep15_csr; + +wire [31:0] ep0_buf0, ep1_buf0, ep2_buf0, ep3_buf0; +wire [31:0] ep4_buf0, ep5_buf0, ep6_buf0, ep7_buf0; +wire [31:0] ep8_buf0, ep9_buf0, ep10_buf0, ep11_buf0; +wire [31:0] ep12_buf0, ep13_buf0, ep14_buf0, ep15_buf0; + +wire [31:0] ep0_buf1, ep1_buf1, ep2_buf1, ep3_buf1; +wire [31:0] ep4_buf1, ep5_buf1, ep6_buf1, ep7_buf1; +wire [31:0] ep8_buf1, ep9_buf1, ep10_buf1, ep11_buf1; +wire [31:0] ep12_buf1, ep13_buf1, ep14_buf1, ep15_buf1; + +wire ep0_dma_in_buf_sz1, ep1_dma_in_buf_sz1; +wire ep2_dma_in_buf_sz1, ep3_dma_in_buf_sz1; +wire ep4_dma_in_buf_sz1, ep5_dma_in_buf_sz1; +wire ep6_dma_in_buf_sz1, ep7_dma_in_buf_sz1; +wire ep8_dma_in_buf_sz1, ep9_dma_in_buf_sz1; +wire ep10_dma_in_buf_sz1, ep11_dma_in_buf_sz1; +wire ep12_dma_in_buf_sz1, ep13_dma_in_buf_sz1; +wire ep14_dma_in_buf_sz1, ep15_dma_in_buf_sz1; + +wire ep0_dma_out_buf_avail, ep1_dma_out_buf_avail; +wire ep2_dma_out_buf_avail, ep3_dma_out_buf_avail; +wire ep4_dma_out_buf_avail, ep5_dma_out_buf_avail; +wire ep6_dma_out_buf_avail, ep7_dma_out_buf_avail; +wire ep8_dma_out_buf_avail, ep9_dma_out_buf_avail; +wire ep10_dma_out_buf_avail, ep11_dma_out_buf_avail; +wire ep12_dma_out_buf_avail, ep13_dma_out_buf_avail; +wire ep14_dma_out_buf_avail, ep15_dma_out_buf_avail; + +reg dma_in_buf_sz1; +reg dma_out_buf_avail; + +reg [31:0] dtmp; +reg [31:0] dout; + +wire [31:0] main_csr; +reg [6:0] funct_adr; +reg [8:0] intb_msk, inta_msk; + +reg match_r1; +reg [31:0] csr; +reg [31:0] buf0; +reg [31:0] buf1; + +reg [3:0] utmi_vend_ctrl; +reg utmi_vend_wr; +reg [7:0] utmi_vend_stat_r; + +reg int_src_re; +reg [8:0] int_srcb; +reg [15:0] int_srca; +reg attach_r, attach_r1; +wire attach, deattach; +reg suspend_r, suspend_r1; +wire suspend_start, suspend_end; +reg usb_reset_r; +reg rx_err_r; +reg nse_err_r; +reg pid_cs_err_r; +reg crc5_err_r; + +reg rf_resume_req_r, rf_resume_req; + +wire inta_ep, intb_ep; +wire inta_rf, intb_rf; +reg inta, intb; + +/////////////////////////////////////////////////////////////////// +// +// WISHBONE Access +// + +// Main CSR Alias +assign main_csr = {27'h0, line_stat, usb_attached, mode_hs, suspend}; + +// Read Registers Logic +always @(adr or main_csr or funct_adr or inta_msk or intb_msk or int_srca + or int_srcb or frm_nat or utmi_vend_stat_r) + case(adr[2:0]) // synopsys full_case parallel_case + 3'h0: dtmp = main_csr; + 3'h1: dtmp = { 25'h0, funct_adr}; + 3'h2: dtmp = { 7'h0, intb_msk, 7'h0, inta_msk}; + 3'h3: dtmp = { 3'h0, int_srcb, 4'h0, int_srca}; + 3'h4: dtmp = frm_nat; + 3'h5: dtmp = { 24'h0, utmi_vend_stat_r}; + endcase + +// Interrupt Source Read Register +always @(posedge wclk) + int_src_re <= adr[6:0] == 7'h3 & re; + +// UTMI Vendor Control Stuff +always @(posedge wclk) + utmi_vend_stat_r <= utmi_vend_stat; + +reg utmi_vend_wr_r; +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) utmi_vend_wr_r <= 1'b0; + else + if(adr[6:0] == 7'h5 && we) utmi_vend_wr_r <= 1'b1; + else + if(utmi_vend_wr) utmi_vend_wr_r <= 1'b0; + +always @(posedge clk) // Second Stage sync + utmi_vend_wr <= utmi_vend_wr_r; + + +reg [3:0] utmi_vend_ctrl_r; +always @(posedge wclk) + if(adr[6:0] == 7'h5 && we) utmi_vend_ctrl_r <= din[3:0]; + +always @(posedge clk) // Second Stage sync + utmi_vend_ctrl <= utmi_vend_ctrl_r; + +// Resume Request +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) rf_resume_req_r <= 1'b0; + else + if(adr[6:0] == 7'h0 && we) rf_resume_req_r <= din[5]; + else + if(rf_resume_req) rf_resume_req_r <= 1'b0; + +always @(posedge clk) // Second Stage sync + rf_resume_req <= rf_resume_req_r; + +// Function Address Register +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) funct_adr <= 7'h0; + else + if(adr[6:0] == 7'h1 && we) funct_adr <= din[6:0]; + +// Interrup Mask Register +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) + begin + inta_msk <= 9'h0; + intb_msk <= 9'h0; + end + else + if(adr[6:0] == 7'h2 && we) + begin + intb_msk <= din[24:16]; + inta_msk <= din[08:00]; + end + +always @(posedge wclk) + case(adr[6:2]) // synopsys full_case parallel_case + 5'h00: dout <= dtmp; // Addr: 0h + 5'h01: dout <= dtmp; + 5'h02: dout <= 32'h0; + 5'h03: dout <= 32'h0; + 5'h04: dout <= ep0_dout; + 5'h05: dout <= ep1_dout; + 5'h06: dout <= ep2_dout; + 5'h07: dout <= ep3_dout; + 5'h08: dout <= ep4_dout; + 5'h09: dout <= ep5_dout; + 5'h0a: dout <= ep6_dout; + 5'h0b: dout <= ep7_dout; + 5'h0c: dout <= ep8_dout; + 5'h0d: dout <= ep9_dout; + 5'h0e: dout <= ep10_dout; + 5'h0f: dout <= ep11_dout; + 5'h10: dout <= ep12_dout; + 5'h11: dout <= ep13_dout; + 5'h12: dout <= ep14_dout; + 5'h13: dout <= ep15_dout; + endcase + +assign ep0_re = (adr[6:2] == 5'h04) & re; +assign ep1_re = (adr[6:2] == 5'h05) & re; +assign ep2_re = (adr[6:2] == 5'h06) & re; +assign ep3_re = (adr[6:2] == 5'h07) & re; +assign ep4_re = (adr[6:2] == 5'h08) & re; +assign ep5_re = (adr[6:2] == 5'h09) & re; +assign ep6_re = (adr[6:2] == 5'h0a) & re; +assign ep7_re = (adr[6:2] == 5'h0b) & re; +assign ep8_re = (adr[6:2] == 5'h0c) & re; +assign ep9_re = (adr[6:2] == 5'h0d) & re; +assign ep10_re = (adr[6:2] == 5'h0e) & re; +assign ep11_re = (adr[6:2] == 5'h0f) & re; +assign ep12_re = (adr[6:2] == 5'h10) & re; +assign ep13_re = (adr[6:2] == 5'h11) & re; +assign ep14_re = (adr[6:2] == 5'h12) & re; +assign ep15_re = (adr[6:2] == 5'h13) & re; + +assign ep0_we = (adr[6:2] == 5'h04) & we; +assign ep1_we = (adr[6:2] == 5'h05) & we; +assign ep2_we = (adr[6:2] == 5'h06) & we; +assign ep3_we = (adr[6:2] == 5'h07) & we; +assign ep4_we = (adr[6:2] == 5'h08) & we; +assign ep5_we = (adr[6:2] == 5'h09) & we; +assign ep6_we = (adr[6:2] == 5'h0a) & we; +assign ep7_we = (adr[6:2] == 5'h0b) & we; +assign ep8_we = (adr[6:2] == 5'h0c) & we; +assign ep9_we = (adr[6:2] == 5'h0d) & we; +assign ep10_we = (adr[6:2] == 5'h0e) & we; +assign ep11_we = (adr[6:2] == 5'h0f) & we; +assign ep12_we = (adr[6:2] == 5'h10) & we; +assign ep13_we = (adr[6:2] == 5'h11) & we; +assign ep14_we = (adr[6:2] == 5'h12) & we; +assign ep15_we = (adr[6:2] == 5'h13) & we; + +/////////////////////////////////////////////////////////////////// +// +// Internal Access +// + +assign match = match_r1; + +always @(posedge clk) + match_r1 <= ep0_match | ep1_match | ep2_match | ep3_match | + ep4_match | ep5_match | ep6_match | ep7_match | + ep8_match | ep9_match | ep10_match | ep11_match | + ep12_match | ep13_match | ep14_match | ep15_match; + +always @(posedge clk) + if(ep0_match) csr <= ep0_csr; + else + if(ep1_match) csr <= ep1_csr; + else + if(ep2_match) csr <= ep2_csr; + else + if(ep3_match) csr <= ep3_csr; + else + if(ep4_match) csr <= ep4_csr; + else + if(ep5_match) csr <= ep5_csr; + else + if(ep6_match) csr <= ep6_csr; + else + if(ep7_match) csr <= ep7_csr; + else + if(ep8_match) csr <= ep8_csr; + else + if(ep9_match) csr <= ep9_csr; + else + if(ep10_match) csr <= ep10_csr; + else + if(ep11_match) csr <= ep11_csr; + else + if(ep12_match) csr <= ep12_csr; + else + if(ep13_match) csr <= ep13_csr; + else + if(ep14_match) csr <= ep14_csr; + else + if(ep15_match) csr <= ep15_csr; + +always @(posedge clk) + if(ep0_match) buf0 <= ep0_buf0; + else + if(ep1_match) buf0 <= ep1_buf0; + else + if(ep2_match) buf0 <= ep2_buf0; + else + if(ep3_match) buf0 <= ep3_buf0; + else + if(ep4_match) buf0 <= ep4_buf0; + else + if(ep5_match) buf0 <= ep5_buf0; + else + if(ep6_match) buf0 <= ep6_buf0; + else + if(ep7_match) buf0 <= ep7_buf0; + else + if(ep8_match) buf0 <= ep8_buf0; + else + if(ep9_match) buf0 <= ep9_buf0; + else + if(ep10_match) buf0 <= ep10_buf0; + else + if(ep11_match) buf0 <= ep11_buf0; + else + if(ep12_match) buf0 <= ep12_buf0; + else + if(ep13_match) buf0 <= ep13_buf0; + else + if(ep14_match) buf0 <= ep14_buf0; + else + if(ep15_match) buf0 <= ep15_buf0; + +always @(posedge clk) + if(ep0_match) buf1 <= ep0_buf1; + else + if(ep1_match) buf1 <= ep1_buf1; + else + if(ep2_match) buf1 <= ep2_buf1; + else + if(ep3_match) buf1 <= ep3_buf1; + else + if(ep4_match) buf1 <= ep4_buf1; + else + if(ep5_match) buf1 <= ep5_buf1; + else + if(ep6_match) buf1 <= ep6_buf1; + else + if(ep7_match) buf1 <= ep7_buf1; + else + if(ep8_match) buf1 <= ep8_buf1; + else + if(ep9_match) buf1 <= ep9_buf1; + else + if(ep10_match) buf1 <= ep10_buf1; + else + if(ep11_match) buf1 <= ep11_buf1; + else + if(ep12_match) buf1 <= ep12_buf1; + else + if(ep13_match) buf1 <= ep13_buf1; + else + if(ep14_match) buf1 <= ep14_buf1; + else + if(ep15_match) buf1 <= ep15_buf1; + +always @(posedge clk) + if(ep0_match) dma_in_buf_sz1 <= ep0_dma_in_buf_sz1; + else + if(ep1_match) dma_in_buf_sz1 <= ep1_dma_in_buf_sz1; + else + if(ep2_match) dma_in_buf_sz1 <= ep2_dma_in_buf_sz1; + else + if(ep3_match) dma_in_buf_sz1 <= ep3_dma_in_buf_sz1; + else + if(ep4_match) dma_in_buf_sz1 <= ep4_dma_in_buf_sz1; + else + if(ep5_match) dma_in_buf_sz1 <= ep5_dma_in_buf_sz1; + else + if(ep6_match) dma_in_buf_sz1 <= ep6_dma_in_buf_sz1; + else + if(ep7_match) dma_in_buf_sz1 <= ep7_dma_in_buf_sz1; + else + if(ep8_match) dma_in_buf_sz1 <= ep8_dma_in_buf_sz1; + else + if(ep9_match) dma_in_buf_sz1 <= ep9_dma_in_buf_sz1; + else + if(ep10_match) dma_in_buf_sz1 <= ep10_dma_in_buf_sz1; + else + if(ep11_match) dma_in_buf_sz1 <= ep11_dma_in_buf_sz1; + else + if(ep12_match) dma_in_buf_sz1 <= ep12_dma_in_buf_sz1; + else + if(ep13_match) dma_in_buf_sz1 <= ep13_dma_in_buf_sz1; + else + if(ep14_match) dma_in_buf_sz1 <= ep14_dma_in_buf_sz1; + else + if(ep15_match) dma_in_buf_sz1 <= ep15_dma_in_buf_sz1; + +always @(posedge clk) + if(ep0_match) dma_out_buf_avail <= ep0_dma_out_buf_avail; + else + if(ep1_match) dma_out_buf_avail <= ep1_dma_out_buf_avail; + else + if(ep2_match) dma_out_buf_avail <= ep2_dma_out_buf_avail; + else + if(ep3_match) dma_out_buf_avail <= ep3_dma_out_buf_avail; + else + if(ep4_match) dma_out_buf_avail <= ep4_dma_out_buf_avail; + else + if(ep5_match) dma_out_buf_avail <= ep5_dma_out_buf_avail; + else + if(ep6_match) dma_out_buf_avail <= ep6_dma_out_buf_avail; + else + if(ep7_match) dma_out_buf_avail <= ep7_dma_out_buf_avail; + else + if(ep8_match) dma_out_buf_avail <= ep8_dma_out_buf_avail; + else + if(ep9_match) dma_out_buf_avail <= ep9_dma_out_buf_avail; + else + if(ep10_match) dma_out_buf_avail <= ep10_dma_out_buf_avail; + else + if(ep11_match) dma_out_buf_avail <= ep11_dma_out_buf_avail; + else + if(ep12_match) dma_out_buf_avail <= ep12_dma_out_buf_avail; + else + if(ep13_match) dma_out_buf_avail <= ep13_dma_out_buf_avail; + else + if(ep14_match) dma_out_buf_avail <= ep14_dma_out_buf_avail; + else + if(ep15_match) dma_out_buf_avail <= ep15_dma_out_buf_avail; + + +/////////////////////////////////////////////////////////////////// +// +// Interrupt Generation +// + +always @(posedge wclk) + attach_r <= usb_attached; + +always @(posedge wclk) + attach_r1 <= attach_r; + +always @(posedge wclk) + suspend_r <= suspend; + +always @(posedge wclk) + suspend_r1 <= suspend_r; + +always @(posedge wclk) + usb_reset_r <= usb_reset; + +always @(posedge wclk) + rx_err_r <= rx_err; + +always @(posedge wclk) + nse_err_r <= nse_err; + +always @(posedge wclk) + pid_cs_err_r <= pid_cs_err; + +always @(posedge wclk) + crc5_err_r <= crc5_err; + +assign attach = !attach_r1 & attach_r; +assign deattach = attach_r1 & !attach_r; +assign suspend_start = !suspend_r1 & suspend_r; +assign suspend_end = suspend_r1 & !suspend_r; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[8] <= 1'b0; + else + if(int_src_re) int_srcb[8] <= 1'b0; + else + if(usb_reset_r) int_srcb[8] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[7] <= 1'b0; + else + if(int_src_re) int_srcb[7] <= 1'b0; + else + if(rx_err_r) int_srcb[7] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[6] <= 1'b0; + else + if(int_src_re) int_srcb[6] <= 1'b0; + else + if(deattach) int_srcb[6] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[5] <= 1'b0; + else + if(int_src_re) int_srcb[5] <= 1'b0; + else + if(attach) int_srcb[5] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[4] <= 1'b0; + else + if(int_src_re) int_srcb[4] <= 1'b0; + else + if(suspend_end) int_srcb[4] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[3] <= 1'b0; + else + if(int_src_re) int_srcb[3] <= 1'b0; + else + if(suspend_start) int_srcb[3] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[2] <= 1'b0; + else + if(int_src_re) int_srcb[2] <= 1'b0; + else + if(nse_err_r) int_srcb[2] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[1] <= 1'b0; + else + if(int_src_re) int_srcb[1] <= 1'b0; + else + if(pid_cs_err_r) int_srcb[1] <= 1'b1; + +`ifdef USBF_ASYNC_RESET +always @(posedge wclk or negedge rst) +`else +always @(posedge wclk) +`endif + if(!rst) int_srcb[0] <= 1'b0; + else + if(int_src_re) int_srcb[0] <= 1'b0; + else + if(crc5_err_r) int_srcb[0] <= 1'b1; + +always @(posedge wclk) + begin + int_srca[15] <= ep15_inta | ep15_intb; + int_srca[14] <= ep14_inta | ep14_intb; + int_srca[13] <= ep13_inta | ep13_intb; + int_srca[12] <= ep12_inta | ep12_intb; + int_srca[11] <= ep11_inta | ep11_intb; + int_srca[10] <= ep10_inta | ep10_intb; + int_srca[09] <= ep9_inta | ep9_intb; + int_srca[08] <= ep8_inta | ep8_intb; + int_srca[07] <= ep7_inta | ep7_intb; + int_srca[06] <= ep6_inta | ep6_intb; + int_srca[05] <= ep5_inta | ep5_intb; + int_srca[04] <= ep4_inta | ep4_intb; + int_srca[03] <= ep3_inta | ep3_intb; + int_srca[02] <= ep2_inta | ep2_intb; + int_srca[01] <= ep1_inta | ep1_intb; + int_srca[00] <= ep0_inta | ep0_intb; + end + +assign inta_ep =ep0_inta | ep1_inta | ep2_inta | ep3_inta | + ep4_inta | ep5_inta | ep6_inta | ep7_inta | + ep8_inta | ep9_inta | ep10_inta | ep11_inta | + ep12_inta | ep13_inta | ep14_inta | ep15_inta; + +assign intb_ep =ep0_intb | ep1_intb | ep2_intb | ep3_intb | + ep4_intb | ep5_intb | ep6_intb | ep7_intb | + ep8_intb | ep9_intb | ep10_intb | ep11_intb | + ep12_intb | ep13_intb | ep14_intb | ep15_intb; + +assign inta_rf = |(int_srcb & inta_msk); +assign intb_rf = |(int_srcb & intb_msk); + +always @(posedge wclk) + inta <= inta_ep | inta_rf; + +always @(posedge wclk) + intb <= intb_ep | intb_rf; + +/////////////////////////////////////////////////////////////////// +// +// Endpoint Register Files +// + +usbf_ep_rf u0( + .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep0_re ), + .we( ep0_we ), + .din( din ), + .dout( ep0_dout ), + .inta( ep0_inta ), + .intb( ep0_intb ), + .dma_req( dma_req[0] ), + .dma_ack( dma_ack[0] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep0_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep0_csr ), + .buf0( ep0_buf0 ), + .buf1( ep0_buf1 ), + .dma_in_buf_sz1( ep0_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep0_dma_out_buf_avail ) + ); + +`ifdef USBF_HAVE_EP1 +usbf_ep_rf u1( + .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep1_re ), + .we( ep1_we ), + .din( din ), + .dout( ep1_dout ), + .inta( ep1_inta ), + .intb( ep1_intb ), + .dma_req( dma_req[1] ), + .dma_ack( dma_ack[1] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep1_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep1_csr ), + .buf0( ep1_buf0 ), + .buf1( ep1_buf1 ), + .dma_in_buf_sz1( ep1_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep1_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u1( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep1_re ), + .we( ep1_we ), + .din( din ), + .dout( ep1_dout ), + .inta( ep1_inta ), + .intb( ep1_intb ), + .dma_req( dma_req[1] ), + .dma_ack( dma_ack[1] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep1_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep1_csr ), + .buf0( ep1_buf0 ), + .buf1( ep1_buf1 ), + .dma_in_buf_sz1( ep1_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep1_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP2 +usbf_ep_rf u2( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep2_re ), + .we( ep2_we ), + .din( din ), + .dout( ep2_dout ), + .inta( ep2_inta ), + .intb( ep2_intb ), + .dma_req( dma_req[2] ), + .dma_ack( dma_ack[2] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep2_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep2_csr ), + .buf0( ep2_buf0 ), + .buf1( ep2_buf1 ), + .dma_in_buf_sz1( ep2_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep2_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u2( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep2_re ), + .we( ep2_we ), + .din( din ), + .dout( ep2_dout ), + .inta( ep2_inta ), + .intb( ep2_intb ), + .dma_req( dma_req[2] ), + .dma_ack( dma_ack[2] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep2_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep2_csr ), + .buf0( ep2_buf0 ), + .buf1( ep2_buf1 ), + .dma_in_buf_sz1( ep2_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep2_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP3 +usbf_ep_rf u3( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep3_re ), + .we( ep3_we ), + .din( din ), + .dout( ep3_dout ), + .inta( ep3_inta ), + .intb( ep3_intb ), + .dma_req( dma_req[3] ), + .dma_ack( dma_ack[3] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep3_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep3_csr ), + .buf0( ep3_buf0 ), + .buf1( ep3_buf1 ), + .dma_in_buf_sz1( ep3_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep3_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u3( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep3_re ), + .we( ep3_we ), + .din( din ), + .dout( ep3_dout ), + .inta( ep3_inta ), + .intb( ep3_intb ), + .dma_req( dma_req[3] ), + .dma_ack( dma_ack[3] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep3_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep3_csr ), + .buf0( ep3_buf0 ), + .buf1( ep3_buf1 ), + .dma_in_buf_sz1( ep3_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep3_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP4 +usbf_ep_rf u4( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep4_re ), + .we( ep4_we ), + .din( din ), + .dout( ep4_dout ), + .inta( ep4_inta ), + .intb( ep4_intb ), + .dma_req( dma_req[4] ), + .dma_ack( dma_ack[4] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep4_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep4_csr ), + .buf0( ep4_buf0 ), + .buf1( ep4_buf1 ), + .dma_in_buf_sz1( ep4_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep4_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u4( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep4_re ), + .we( ep4_we ), + .din( din ), + .dout( ep4_dout ), + .inta( ep4_inta ), + .intb( ep4_intb ), + .dma_req( dma_req[4] ), + .dma_ack( dma_ack[4] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep4_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep4_csr ), + .buf0( ep4_buf0 ), + .buf1( ep4_buf1 ), + .dma_in_buf_sz1( ep4_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep4_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP5 +usbf_ep_rf u5( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep5_re ), + .we( ep5_we ), + .din( din ), + .dout( ep5_dout ), + .inta( ep5_inta ), + .intb( ep5_intb ), + .dma_req( dma_req[5] ), + .dma_ack( dma_ack[5] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep5_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep5_csr ), + .buf0( ep5_buf0 ), + .buf1( ep5_buf1 ), + .dma_in_buf_sz1( ep5_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep5_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u5( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep5_re ), + .we( ep5_we ), + .din( din ), + .dout( ep5_dout ), + .inta( ep5_inta ), + .intb( ep5_intb ), + .dma_req( dma_req[5] ), + .dma_ack( dma_ack[5] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep5_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep5_csr ), + .buf0( ep5_buf0 ), + .buf1( ep5_buf1 ), + .dma_in_buf_sz1( ep5_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep5_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP6 +usbf_ep_rf u6( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep6_re ), + .we( ep6_we ), + .din( din ), + .dout( ep6_dout ), + .inta( ep6_inta ), + .intb( ep6_intb ), + .dma_req( dma_req[6] ), + .dma_ack( dma_ack[6] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep6_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep6_csr ), + .buf0( ep6_buf0 ), + .buf1( ep6_buf1 ), + .dma_in_buf_sz1( ep6_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep6_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u6( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep6_re ), + .we( ep6_we ), + .din( din ), + .dout( ep6_dout ), + .inta( ep6_inta ), + .intb( ep6_intb ), + .dma_req( dma_req[6] ), + .dma_ack( dma_ack[6] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep6_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep6_csr ), + .buf0( ep6_buf0 ), + .buf1( ep6_buf1 ), + .dma_in_buf_sz1( ep6_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep6_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP7 +usbf_ep_rf u7( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep7_re ), + .we( ep7_we ), + .din( din ), + .dout( ep7_dout ), + .inta( ep7_inta ), + .intb( ep7_intb ), + .dma_req( dma_req[7] ), + .dma_ack( dma_ack[7] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep7_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep7_csr ), + .buf0( ep7_buf0 ), + .buf1( ep7_buf1 ), + .dma_in_buf_sz1( ep7_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep7_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u7( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep7_re ), + .we( ep7_we ), + .din( din ), + .dout( ep7_dout ), + .inta( ep7_inta ), + .intb( ep7_intb ), + .dma_req( dma_req[7] ), + .dma_ack( dma_ack[7] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep7_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep7_csr ), + .buf0( ep7_buf0 ), + .buf1( ep7_buf1 ), + .dma_in_buf_sz1( ep7_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep7_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP8 +usbf_ep_rf u8( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep8_re ), + .we( ep8_we ), + .din( din ), + .dout( ep8_dout ), + .inta( ep8_inta ), + .intb( ep8_intb ), + .dma_req( dma_req[8] ), + .dma_ack( dma_ack[8] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep8_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep8_csr ), + .buf0( ep8_buf0 ), + .buf1( ep8_buf1 ), + .dma_in_buf_sz1( ep8_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep8_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u8( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep8_re ), + .we( ep8_we ), + .din( din ), + .dout( ep8_dout ), + .inta( ep8_inta ), + .intb( ep8_intb ), + .dma_req( dma_req[8] ), + .dma_ack( dma_ack[8] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep8_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep8_csr ), + .buf0( ep8_buf0 ), + .buf1( ep8_buf1 ), + .dma_in_buf_sz1( ep8_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep8_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP9 +usbf_ep_rf u9( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep9_re ), + .we( ep9_we ), + .din( din ), + .dout( ep9_dout ), + .inta( ep9_inta ), + .intb( ep9_intb ), + .dma_req( dma_req[9] ), + .dma_ack( dma_ack[9] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep9_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep9_csr ), + .buf0( ep9_buf0 ), + .buf1( ep9_buf1 ), + .dma_in_buf_sz1( ep9_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep9_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u9( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep9_re ), + .we( ep9_we ), + .din( din ), + .dout( ep9_dout ), + .inta( ep9_inta ), + .intb( ep9_intb ), + .dma_req( dma_req[9] ), + .dma_ack( dma_ack[9] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep9_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep9_csr ), + .buf0( ep9_buf0 ), + .buf1( ep9_buf1 ), + .dma_in_buf_sz1( ep9_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep9_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP10 +usbf_ep_rf u10( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep10_re ), + .we( ep10_we ), + .din( din ), + .dout( ep10_dout ), + .inta( ep10_inta ), + .intb( ep10_intb ), + .dma_req( dma_req[10] ), + .dma_ack( dma_ack[10] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep10_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep10_csr ), + .buf0( ep10_buf0 ), + .buf1( ep10_buf1 ), + .dma_in_buf_sz1( ep10_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep10_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u10( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep10_re ), + .we( ep10_we ), + .din( din ), + .dout( ep10_dout ), + .inta( ep10_inta ), + .intb( ep10_intb ), + .dma_req( dma_req[10] ), + .dma_ack( dma_ack[10] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep10_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep10_csr ), + .buf0( ep10_buf0 ), + .buf1( ep10_buf1 ), + .dma_in_buf_sz1( ep10_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep10_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP11 +usbf_ep_rf u11( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep11_re ), + .we( ep11_we ), + .din( din ), + .dout( ep11_dout ), + .inta( ep11_inta ), + .intb( ep11_intb ), + .dma_req( dma_req[11] ), + .dma_ack( dma_ack[11] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep11_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep11_csr ), + .buf0( ep11_buf0 ), + .buf1( ep11_buf1 ), + .dma_in_buf_sz1( ep11_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep11_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u11( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep11_re ), + .we( ep11_we ), + .din( din ), + .dout( ep11_dout ), + .inta( ep11_inta ), + .intb( ep11_intb ), + .dma_req( dma_req[11] ), + .dma_ack( dma_ack[11] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep11_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep11_csr ), + .buf0( ep11_buf0 ), + .buf1( ep11_buf1 ), + .dma_in_buf_sz1( ep11_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep11_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP12 +usbf_ep_rf u12( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep12_re ), + .we( ep12_we ), + .din( din ), + .dout( ep12_dout ), + .inta( ep12_inta ), + .intb( ep12_intb ), + .dma_req( dma_req[12] ), + .dma_ack( dma_ack[12] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep12_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep12_csr ), + .buf0( ep12_buf0 ), + .buf1( ep12_buf1 ), + .dma_in_buf_sz1( ep12_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep12_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u12( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep12_re ), + .we( ep12_we ), + .din( din ), + .dout( ep12_dout ), + .inta( ep12_inta ), + .intb( ep12_intb ), + .dma_req( dma_req[12] ), + .dma_ack( dma_ack[12] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep12_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep12_csr ), + .buf0( ep12_buf0 ), + .buf1( ep12_buf1 ), + .dma_in_buf_sz1( ep12_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep12_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP13 +usbf_ep_rf u13( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep13_re ), + .we( ep13_we ), + .din( din ), + .dout( ep13_dout ), + .inta( ep13_inta ), + .intb( ep13_intb ), + .dma_req( dma_req[13] ), + .dma_ack( dma_ack[13] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep13_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep13_csr ), + .buf0( ep13_buf0 ), + .buf1( ep13_buf1 ), + .dma_in_buf_sz1( ep13_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep13_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u13( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep13_re ), + .we( ep13_we ), + .din( din ), + .dout( ep13_dout ), + .inta( ep13_inta ), + .intb( ep13_intb ), + .dma_req( dma_req[13] ), + .dma_ack( dma_ack[13] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep13_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep13_csr ), + .buf0( ep13_buf0 ), + .buf1( ep13_buf1 ), + .dma_in_buf_sz1( ep13_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep13_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP14 +usbf_ep_rf u14( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep14_re ), + .we( ep14_we ), + .din( din ), + .dout( ep14_dout ), + .inta( ep14_inta ), + .intb( ep14_intb ), + .dma_req( dma_req[14] ), + .dma_ack( dma_ack[14] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep14_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep14_csr ), + .buf0( ep14_buf0 ), + .buf1( ep14_buf1 ), + .dma_in_buf_sz1( ep14_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep14_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u14( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep14_re ), + .we( ep14_we ), + .din( din ), + .dout( ep14_dout ), + .inta( ep14_inta ), + .intb( ep14_intb ), + .dma_req( dma_req[14] ), + .dma_ack( dma_ack[14] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep14_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep14_csr ), + .buf0( ep14_buf0 ), + .buf1( ep14_buf1 ), + .dma_in_buf_sz1( ep14_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep14_dma_out_buf_avail ) + ); +`endif + +`ifdef USBF_HAVE_EP15 +usbf_ep_rf u15( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep15_re ), + .we( ep15_we ), + .din( din ), + .dout( ep15_dout ), + .inta( ep15_inta ), + .intb( ep15_intb ), + .dma_req( dma_req[15] ), + .dma_ack( dma_ack[15] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep15_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep15_csr ), + .buf0( ep15_buf0 ), + .buf1( ep15_buf1 ), + .dma_in_buf_sz1( ep15_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep15_dma_out_buf_avail ) + ); + +`else +usbf_ep_rf_dummy u15( .clk( clk ), + .wclk( wclk ), + .rst( rst ), + .adr( adr[1:0] ), + .re( ep15_re ), + .we( ep15_we ), + .din( din ), + .dout( ep15_dout ), + .inta( ep15_inta ), + .intb( ep15_intb ), + .dma_req( dma_req[15] ), + .dma_ack( dma_ack[15] ), + .idin( idin ), + .ep_sel( ep_sel ), + .ep_match( ep15_match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( ep15_csr ), + .buf0( ep15_buf0 ), + .buf1( ep15_buf1 ), + .dma_in_buf_sz1( ep15_dma_in_buf_sz1 ), + .dma_out_buf_avail( ep15_dma_out_buf_avail ) + ); +`endif + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v new file mode 100644 index 000000000..029f9e145 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v @@ -0,0 +1,622 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB function core //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_top.v,v 1.7 2003/11/11 07:15:16 rudi Exp $ +// +// $Date: 2003/11/11 07:15:16 $ +// $Revision: 1.7 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_top.v,v $ +// Revision 1.7 2003/11/11 07:15:16 rudi +// Fixed Resume signaling and initial attachment +// +// Revision 1.6 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.5 2001/11/04 12:22:45 rudi +// +// - Fixed previous fix (brocke something else ...) +// - Majore Synthesis cleanup +// +// Revision 1.4 2001/11/03 03:26:23 rudi +// +// - Fixed several interrupt and error condition reporting bugs +// +// Revision 1.3 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:52 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.2 2001/03/07 09:08:13 rudi +// +// Added USB control signaling (Line Status) block. Fixed some minor +// typos, added resume bit and signal. +// +// Revision 0.1.0.1 2001/02/28 08:11:40 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_top(// WISHBONE Interface + clk_i, rst_i, wb_addr_i, wb_data_i, wb_data_o, + wb_ack_o, wb_we_i, wb_stb_i, wb_cyc_i, inta_o, intb_o, + dma_req_o, dma_ack_i, susp_o, resume_req_i, + + // UTMI Interface + phy_clk_pad_i, phy_rst_pad_o, + DataOut_pad_o, TxValid_pad_o, TxReady_pad_i, + + RxValid_pad_i, RxActive_pad_i, RxError_pad_i, + DataIn_pad_i, XcvSelect_pad_o, TermSel_pad_o, + SuspendM_pad_o, LineState_pad_i, + + OpMode_pad_o, usb_vbus_pad_i, + VControl_Load_pad_o, VControl_pad_o, VStatus_pad_i, + + // Buffer Memory Interface + sram_adr_o, sram_data_i, sram_data_o, sram_re_o, sram_we_o + + ); + +parameter SSRAM_HADR = `USBF_SSRAM_HADR; +input clk_i; +input rst_i; +input [`USBF_UFC_HADR:0] wb_addr_i; +input [31:0] wb_data_i; +output [31:0] wb_data_o; +output wb_ack_o; +input wb_we_i; +input wb_stb_i; +input wb_cyc_i; +output inta_o; +output intb_o; +output [15:0] dma_req_o; +input [15:0] dma_ack_i; +output susp_o; +input resume_req_i; + +input phy_clk_pad_i; +output phy_rst_pad_o; + +output [7:0] DataOut_pad_o; +output TxValid_pad_o; +input TxReady_pad_i; + +input [7:0] DataIn_pad_i; +input RxValid_pad_i; +input RxActive_pad_i; +input RxError_pad_i; + +output XcvSelect_pad_o; +output TermSel_pad_o; +output SuspendM_pad_o; +input [1:0] LineState_pad_i; +output [1:0] OpMode_pad_o; +input usb_vbus_pad_i; +output VControl_Load_pad_o; +output [3:0] VControl_pad_o; +input [7:0] VStatus_pad_i; + +output [SSRAM_HADR:0] sram_adr_o; +input [31:0] sram_data_i; +output [31:0] sram_data_o; +output sram_re_o; +output sram_we_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +// UTMI Interface +wire [7:0] rx_data; +wire rx_valid, rx_active, rx_err; +wire [7:0] tx_data; +wire tx_valid; +wire tx_ready; +wire tx_first; +wire tx_valid_last; + +// Misc UTMI USB status +wire mode_hs; // High Speed Mode +wire usb_reset; // USB Reset +wire usb_suspend; // USB Sleep +wire usb_attached; // Attached to USB +wire resume_req; // Resume Request + +// Memory Arbiter Interface +wire [SSRAM_HADR:0] madr; // word address +wire [31:0] mdout; +wire [31:0] mdin; +wire mwe; +wire mreq; +wire mack; +wire rst; + +// Wishbone Memory interface +wire [`USBF_UFC_HADR:0] ma_adr; +wire [31:0] ma2wb_d; +wire [31:0] wb2ma_d; +wire ma_we; +wire ma_req; +wire ma_ack; + +// WISHBONE Register File interface +wire rf_re; +wire rf_we; +wire [31:0] wb2rf_d; +wire [31:0] rf2wb_d; + +// Internal Register File Interface +wire [6:0] funct_adr; // This functions address (set by controller) +wire [31:0] idin; // Data Input +wire [3:0] ep_sel; // Endpoint Number Input +wire match; // Endpoint Matched +wire dma_in_buf_sz1; +wire dma_out_buf_avail; +wire buf0_rl; // Reload Buf 0 with original values +wire buf0_set; // Write to buf 0 +wire buf1_set; // Write to buf 1 +wire uc_bsel_set; // Write to the uc_bsel field +wire uc_dpd_set; // Write to the uc_dpd field +wire int_buf1_set; // Set buf1 full/empty interrupt +wire int_buf0_set; // Set buf0 full/empty interrupt +wire int_upid_set; // Set unsupported PID interrupt +wire int_crc16_set; // Set CRC16 error interrupt +wire int_to_set; // Set time out interrupt +wire int_seqerr_set; // Set PID sequence error interrupt +wire out_to_small; // OUT packet was to small for DMA operation +wire [31:0] csr; // Internal CSR Output +wire [31:0] buf0; // Internal Buf 0 Output +wire [31:0] buf1; // Internal Buf 1 Output +wire [31:0] frm_nat; // Frame Number and Time Register +wire nse_err; // No Such Endpoint Error +wire pid_cs_err; // PID CS error +wire crc5_err; // CRC5 Error +wire rf_resume_req; // Resume Request From main CSR + +reg susp_o; +reg [1:0] LineState_r; // Added to make a full synchronizer +reg [7:0] VStatus_r; // Added to make a full synchronizer + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// +assign rst = rst_i; +assign phy_rst_pad_o = rst_i; +assign resume_req = resume_req_i; + +always @(posedge clk_i) + susp_o <= usb_suspend; + +always @(posedge phy_clk_pad_i) // First Stage Synchronizer + LineState_r <= LineState_pad_i; + +always @(posedge phy_clk_pad_i) // First Stage Synchronizer + VStatus_r <= VStatus_pad_i; + +/////////////////////////////////////////////////////////////////// +// +// Module Instantiations +// + +reg resume_req_r; +reg suspend_clr_wr; +wire suspend_clr; + +always @(posedge clk_i) + suspend_clr_wr <= suspend_clr; + +`ifdef USBF_ASYNC_RESET +always @(posedge clk_i or negedge rst) +`else +always @(posedge clk_i) +`endif + if(!rst) resume_req_r <= 1'b0; + else + if(suspend_clr_wr) resume_req_r <= 1'b0; + else + if(resume_req) resume_req_r <= 1'b1; + + +// UTMI Interface +usbf_utmi_if u0( + .phy_clk( phy_clk_pad_i ), + .rst( rst ), + .DataOut( DataOut_pad_o ), + .TxValid( TxValid_pad_o ), + .TxReady( TxReady_pad_i ), + .RxValid( RxValid_pad_i ), + .RxActive( RxActive_pad_i ), + .RxError( RxError_pad_i ), + .DataIn( DataIn_pad_i ), + .XcvSelect( XcvSelect_pad_o ), + .TermSel( TermSel_pad_o ), + .SuspendM( SuspendM_pad_o ), + .LineState( LineState_pad_i ), + .OpMode( OpMode_pad_o ), + .usb_vbus( usb_vbus_pad_i ), + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ), + .mode_hs( mode_hs ), + .usb_reset( usb_reset ), + .usb_suspend( usb_suspend ), + .usb_attached( usb_attached ), + .resume_req( resume_req_r ), + .suspend_clr( suspend_clr ) + ); + +// Protocol Layer +usbf_pl #(SSRAM_HADR) + u1( .clk( phy_clk_pad_i ), + .rst( rst ), + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ), + .tx_valid_out( TxValid_pad_o ), + .mode_hs( mode_hs ), + .usb_reset( usb_reset ), + .usb_suspend( usb_suspend ), + .usb_attached( usb_attached ), + .madr( madr ), + .mdout( mdout ), + .mdin( mdin ), + .mwe( mwe ), + .mreq( mreq ), + .mack( mack ), + .fa( funct_adr ), + .dma_in_buf_sz1( dma_in_buf_sz1 ), + .dma_out_buf_avail( dma_out_buf_avail ), + .idin( idin ), + .ep_sel( ep_sel ), + .match( match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( csr ), + .buf0( buf0 ), + .buf1( buf1 ), + .frm_nat( frm_nat ), + .pid_cs_err( pid_cs_err ), + .nse_err( nse_err ), + .crc5_err( crc5_err ) + ); + +// Memory Arbiter +usbf_mem_arb #(SSRAM_HADR) + u2( .phy_clk( phy_clk_pad_i ), + .wclk( clk_i ), + .rst( rst ), + + .sram_adr( sram_adr_o ), + .sram_din( sram_data_i ), + .sram_dout( sram_data_o ), + .sram_re( sram_re_o ), + .sram_we( sram_we_o ), + + .madr( madr ), + .mdout( mdin ), + .mdin( mdout ), + .mwe( mwe ), + .mreq( mreq ), + .mack( mack ), + + .wadr( ma_adr[SSRAM_HADR + 2:2] ), + .wdout( ma2wb_d ), + .wdin( wb2ma_d ), + .wwe( ma_we ), + .wreq( ma_req ), + .wack( ma_ack ) + ); + +// Register File +usbf_rf u4( .clk( phy_clk_pad_i ), + .wclk( clk_i ), + .rst( rst ), + + .adr( ma_adr[8:2] ), + .re( rf_re ), + .we( rf_we ), + .din( wb2rf_d ), + .dout( rf2wb_d ), + + .inta( inta_o ), + .intb( intb_o ), + .dma_req( dma_req_o ), + .dma_ack( dma_ack_i ), + .idin( idin ), + .ep_sel( ep_sel ), + .match( match ), + .buf0_rl( buf0_rl ), + .buf0_set( buf0_set ), + .buf1_set( buf1_set ), + .uc_bsel_set( uc_bsel_set ), + .uc_dpd_set( uc_dpd_set ), + .int_buf1_set( int_buf1_set ), + .int_buf0_set( int_buf0_set ), + .int_upid_set( int_upid_set ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .out_to_small( out_to_small ), + .csr( csr ), + .buf0( buf0 ), + .buf1( buf1 ), + .funct_adr( funct_adr ), + .dma_in_buf_sz1( dma_in_buf_sz1 ), + .dma_out_buf_avail( dma_out_buf_avail ), + .frm_nat( frm_nat ), + .utmi_vend_stat( VStatus_r ), + .utmi_vend_ctrl( VControl_pad_o ), + .utmi_vend_wr( VControl_Load_pad_o ), + .line_stat( LineState_r ), + .usb_attached( usb_attached ), + .mode_hs( mode_hs ), + .suspend( usb_suspend ), + .attached( usb_attached ), + .usb_reset( usb_reset ), + .pid_cs_err( pid_cs_err ), + .nse_err( nse_err ), + .crc5_err( crc5_err ), + .rx_err( rx_err ), + .rf_resume_req( rf_resume_req ) + ); + + +// WISHBONE Interface +usbf_wb u5( .phy_clk( phy_clk_pad_i ), + .wb_clk( clk_i ), + .rst( rst ), + .wb_addr_i( wb_addr_i ), + .wb_data_i( wb_data_i ), + .wb_data_o( wb_data_o ), + .wb_ack_o( wb_ack_o ), + .wb_we_i( wb_we_i ), + .wb_stb_i( wb_stb_i ), + .wb_cyc_i( wb_cyc_i ), + + .ma_adr( ma_adr ), + .ma_dout( wb2ma_d ), + .ma_din( ma2wb_d ), + .ma_we( ma_we ), + .ma_req( ma_req ), + .ma_ack( ma_ack ), + + .rf_re( rf_re ), + .rf_we( rf_we ), + .rf_dout( wb2rf_d ), + .rf_din( rf2wb_d ) + ); + + +/////////////////////////////////////////////////////////////////// +// +// Initialization +// This section does not add any functionality. It is only provided +// to make sure that the core is configured properly and to provide +// configuration information for simulations. +// + +// synopsys translate_off +integer ep_cnt, ep_cnt2; +reg [15:0] ep_check; +initial + begin + $display("\n"); + ep_cnt = 1; + ep_cnt2 = 0; + ep_check = 0; + +`ifdef USBF_HAVE_EP1 + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP2 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP3 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP4 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP5 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP6 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP7 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP8 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP9 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP10 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP11 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP12 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP13 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP14 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif +ep_cnt2 = ep_cnt2 + 1; +`ifdef USBF_HAVE_EP15 + if(!ep_check[ep_cnt2-1]) + $display("ERROR: USBF_TOP: Endpoint %0d not defined but endpoint %0d defined", ep_cnt2, ep_cnt2+1); + ep_cnt = ep_cnt + 1; + ep_check[ep_cnt2] = 1; +`endif + + $display(""); + $display("INFO: USB Function core instantiated (%m)"); + $display(" Supported Endpoints: %0d (0 through %0d)",ep_cnt, ep_cnt-1); + $display(" WISHBONE Address bus size: A%0d:0", `USBF_UFC_HADR ); + $display(" SSRAM Address bus size: A%0d:0", SSRAM_HADR ); + $display(" Buffer Memory Size: %0d bytes", (1< `USBF_T1_C_2_5_US); + +always @(posedge clk) // Smaller Than 3 mS (Actual Time will be 0-2.9375mS) + T1_st_3_0_mS <= !idle_cnt_clr & (idle_cnt1 < `USBF_T1_C_3_0_MS); + +always @(posedge clk) // Greater Than 3 mS (Actual Time will be T0+3.0625mS) + T1_gt_3_0_mS <= !idle_cnt_clr & (idle_cnt1 > `USBF_T1_C_3_0_MS); + +always @(posedge clk) // Greater Than 3.125 mS (Actual Time will be T0+3.1875uS) + T1_gt_3_125_mS <= !idle_cnt_clr & (idle_cnt1 > `USBF_T1_C_3_125_MS); + +always @(posedge clk) // Greater Than 3.125 mS (Actual Time will be T0+3.1875uS) + T1_gt_5_0_mS <= !idle_cnt_clr & (idle_cnt1 > `USBF_T1_C_5_MS); + +// --------------------------------------------------------- +// Misc Events Counter + +// Pre-scaler - 2.5uS +always @(posedge clk) + if(me_cnt_clr || me_ps_2_5_us) me_ps <= 8'h0; + else me_ps <= me_ps + 8'h1; + +always @(posedge clk) // Generate a pulse every 2.5 uS + me_ps_2_5_us <= (me_ps == `USBF_T2_C_2_5_US); + +// Second Pre-scaler - 0.5mS +always @(posedge clk) + if(me_cnt_clr || me_ps2_0_5_ms ) me_ps2 <= 8'h0; + else + if(me_ps_2_5_us) me_ps2 <= me_ps2 + 8'h1; + +always @(posedge clk) // Generate a pulse every 0.5 mS + me_ps2_0_5_ms <= (me_ps2 == `USBF_T2_C_0_5_MS) & !me_ps2_0_5_ms; + +// final misc Counter +always @(posedge clk) + if(me_cnt_clr) me_cnt <= 8'h0; + else + if(!me_cnt_100_ms && me_ps2_0_5_ms) me_cnt <= me_cnt + 8'h1; + +always @(posedge clk) // Indicate when 100uS have passed + T2_gt_100_uS <= !me_cnt_clr & (me_ps2 > `USBF_T2_C_100_US); // Actual Time: 102.5 uS + +always @(posedge clk) // Indicate when wakeup period has passed + T2_wakeup <= !me_cnt_clr & (me_cnt > `USBF_T2_C_WAKEUP); + +always @(posedge clk) // Indicate when 1 mS has passed + T2_gt_1_0_mS <= !me_cnt_clr & (me_cnt > `USBF_T2_C_1_0_MS); // Actual Time: 1.5 mS + +always @(posedge clk) // Indicate when 1.2 mS has passed + T2_gt_1_2_mS <= !me_cnt_clr & (me_cnt > `USBF_T2_C_1_2_MS); // Actual Time: 1.5 mS + +always @(posedge clk) // Generate a pulse after 100 mS + me_cnt_100_ms <= !me_cnt_clr & (me_cnt == `USBF_T2_C_100_MS); // Actual Time: 100 mS + +// --------------------------------------------------------- +// Chirp Counter + +always @(posedge clk) + if(chirp_cnt_clr) chirp_cnt <= 3'h0; + else + if(chirp_cnt_inc) chirp_cnt <= chirp_cnt + 3'h1; + +always @(posedge clk) + chirp_cnt_is_6 <= (chirp_cnt == 3'h6); + +/////////////////////////////////////////////////////////////////// +// +// Main State Machine +// + +`ifdef USBF_ASYNC_RESET +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= POR; + else + if(usb_vbus) state <= POR; + else state <= next_state; + +always @(state or mode_hs or idle_long or resume_req_s or me_cnt_100_ms or + j_long or k_long or se0_long or ls_se0 or + T1_gt_2_5_uS or T1_st_3_0_mS or T1_gt_3_0_mS or + T1_gt_5_0_mS or T2_gt_100_uS or T2_wakeup or T2_gt_1_0_mS or + T2_gt_1_2_mS or chirp_cnt_is_6) + begin + next_state = state; // Default don't change state + + mode_set_hs = 1'b0; + mode_set_fs = 1'b0; + suspend_set = 1'b0; + suspend_clr = 1'b0; + attached_set = 1'b0; + attached_clr = 1'b0; + usb_reset_d = 1'b0; + + fs_term_on = 1'b0; + fs_term_off = 1'b0; + xcv_set_hs = 1'b0; + xcv_set_fs = 1'b0; + bit_stuff_on = 1'b0; + bit_stuff_off = 1'b0; + + idle_cnt_clr = 1'b0; + me_cnt_clr = 1'b0; + drive_k_d = 1'b0; + chirp_cnt_clr = 1'b0; + chirp_cnt_inc = 1'b0; + + case(state) // synopsys full_case parallel_case + POR: // Power On/Reset + begin + me_cnt_clr = 1'b1; + xcv_set_fs = 1'b1; + fs_term_on = 1'b1; + mode_set_fs = 1'b1; + attached_clr = 1'b1; + bit_stuff_on = 1'b0; + suspend_clr = 1'b1; + next_state = ATTACH; + end + + NORMAL: // Normal Operation + begin + if(!mode_hs && T1_gt_2_5_uS && T1_st_3_0_mS && !idle_long) + begin + me_cnt_clr = 1'b1; + next_state = RESET; + end + else + if(!mode_hs && T1_gt_3_0_mS) + begin + idle_cnt_clr = 1'b1; + suspend_set = 1'b1; + next_state = SUSPEND; + end + else + if(mode_hs && T1_gt_3_0_mS) + begin // Switch to FS mode, and decide + // if it's a RESET or SUSPEND + me_cnt_clr = 1'b1; + xcv_set_fs = 1'b1; + fs_term_on = 1'b1; + next_state = RES_SUSP; + end + end + + RES_SUSP: // Decide if it's a Reset or Suspend Signaling + begin // We are now in FS mode, wait 100uS first + if(T2_gt_100_uS && se0_long) + begin + me_cnt_clr = 1'b1; + next_state = RESET; + end + else + if(T2_gt_100_uS && j_long) + begin + idle_cnt_clr = 1'b1; + suspend_set = 1'b1; + next_state = SUSPEND; + end + end + + SUSPEND: // In Suspend + begin + if(T1_gt_2_5_uS && se0_long) + begin + suspend_clr = 1'b1; + me_cnt_clr = 1'b1; + next_state = RESET; + end + else + if(k_long) // Start Resuming + next_state = RESUME; + else + if(T1_gt_5_0_mS && resume_req_s) + next_state = RESUME_REQUEST; + end + + RESUME: + begin + suspend_clr = 1'b1; + if(ls_se0) + begin + if(mode_hs) + begin // Switch Back to HS mode + xcv_set_hs = 1'b1; + fs_term_off = 1'b1; + end + bit_stuff_on = 1'b1; // Enable Bit Stuffing and NRZI encoding + me_cnt_clr = 1'b1; + next_state = RESUME_WAIT; + end + end + + RESUME_WAIT: + begin + if(T2_gt_100_uS) next_state = NORMAL; + end + + RESUME_REQUEST: // Function Resume Request + begin + suspend_clr = 1'b1; + // Wait for internal wake up + if(T2_wakeup) + begin + fs_term_on = 1'b1; // Switch Termination to Full Speed + bit_stuff_off = 1'b1; // disable Bit Stuffing and NRZI encoding + me_cnt_clr = 1'b1; + next_state = RESUME_SIG; + end + end + + RESUME_SIG: // Signal resume + begin + // Drive Resume ('K') for 1-15 mS + drive_k_d = 1'b1; + // Stop driving after 1.5 mS + if(T2_gt_1_0_mS) next_state = RESUME; + end + + ATTACH: // Attach To USB Detected + begin + idle_cnt_clr = 1'b1; + if(me_cnt_100_ms) + //if(me_cnt_100_ms && j_long) + begin + attached_set = 1'b1; + next_state = NORMAL; + end + /* + if(me_cnt_100_ms && se0_long) + begin + attached_set = 1'b1; + me_cnt_clr = 1'b1; + next_state = RESET; + end + */ + end + + RESET: // In Reset + begin + usb_reset_d = 1'b1; // Assert Internal USB Reset + xcv_set_hs = 1'b1; // Switch xcvr to HS mode + fs_term_on = 1'b1; // Turn FS termination On + mode_set_fs = 1'b1; // Change mode to FS + bit_stuff_off = 1'b1; // disable Bit Stuffing and NRZI encoding + // Get out of reset after 1.5 mS + if(T2_gt_1_0_mS) + begin + me_cnt_clr = 1'b1; + next_state = SPEED_NEG; + end + end + + SPEED_NEG: // Speed Negotiation + begin + drive_k_d = 1'b1; + chirp_cnt_clr = 1'b1; + // Start looking for 'K' after 1.5 mS + if(T2_gt_1_2_mS) next_state = SPEED_NEG_K; + end + + SPEED_NEG_K: + begin + if(chirp_cnt_is_6) next_state = SPEED_NEG_HS; + else + begin + if(k_long) + begin + chirp_cnt_inc = 1'b1; + next_state = SPEED_NEG_J; + end + if(se0_long) + next_state = SPEED_NEG_FS; + end + end + + SPEED_NEG_J: + begin + if(chirp_cnt_is_6) next_state = SPEED_NEG_HS; + else + begin + if(j_long) + begin + chirp_cnt_inc = 1'b1; + next_state = SPEED_NEG_K; + end + if(se0_long) + next_state = SPEED_NEG_FS; + end + end + + SPEED_NEG_HS: + begin + bit_stuff_on = 1'b1; // Enable Bit Stuffing and NRZI encoding + xcv_set_hs = 1'b1; // Switch xcvr to HS mode + fs_term_off = 1'b1; // Turn FS termination Off + mode_set_hs = 1'b1; // Change mode to HS + if(se0_long) next_state = NORMAL; + end + + SPEED_NEG_FS: + begin + bit_stuff_on = 1'b1; // Enable Bit Stuffing and NRZI encoding + xcv_set_fs = 1'b1; // Switch xcvr to FS mode + fs_term_on = 1'b1; // Turn FS termination On + mode_set_fs = 1'b1; // Change mode to FS + next_state = NORMAL; + end + + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v new file mode 100644 index 000000000..30428d476 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v @@ -0,0 +1,282 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Interface //// +//// This is the external bus interface, that is WISHBONE //// +//// SoC compliant. //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2003 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usbf_wb.v,v 1.4 2003/10/17 02:36:57 rudi Exp $ +// +// $Date: 2003/10/17 02:36:57 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usbf_wb.v,v $ +// Revision 1.4 2003/10/17 02:36:57 rudi +// - Disabling bit stuffing and NRZI encoding during speed negotiation +// - Now the core can send zero size packets +// - Fixed register addresses for some of the higher endpoints +// (conversion between decimal/hex was wrong) +// - The core now does properly evaluate the function address to +// determine if the packet was intended for it. +// - Various other minor bugs and typos +// +// Revision 1.3 2001/09/24 01:15:28 rudi +// +// Changed reset to be active high async. +// +// Revision 1.2 2001/08/10 08:48:33 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// +// Revision 1.1 2001/08/03 05:30:09 rudi +// +// +// 1) Reorganized directory structure +// +// Revision 1.2 2001/03/31 13:00:52 rudi +// +// - Added Core configuration +// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode +// - Modified WISHBONE interface and sync logic +// - Moved SSRAM outside the core (added interface) +// - Many small bug fixes ... +// +// Revision 1.0 2001/03/07 09:17:12 rudi +// +// +// Changed all revisions to revision 1.0. This is because OpenCores CVS +// interface could not handle the original '0.1' revision .... +// +// Revision 0.1.0.1 2001/02/28 08:11:47 rudi +// Initial Release +// +// + +`include "usbf_defines.v" + +module usbf_wb( // WISHBONE Interface + wb_clk, phy_clk, rst, wb_addr_i, wb_data_i, wb_data_o, + wb_ack_o, wb_we_i, wb_stb_i, wb_cyc_i, + + // Memory Arbiter Interface + ma_adr, ma_dout, ma_din, ma_we, ma_req, ma_ack, + + // Register File interface + rf_re, rf_we, rf_din, rf_dout); + +input wb_clk, phy_clk; +input rst; +input [`USBF_UFC_HADR:0] wb_addr_i; +input [31:0] wb_data_i; +output [31:0] wb_data_o; +output wb_ack_o; +input wb_we_i; +input wb_stb_i; +input wb_cyc_i; + +// Memory Arbiter Interface +output [`USBF_UFC_HADR:0] ma_adr; +output [31:0] ma_dout; +input [31:0] ma_din; +output ma_we; +output ma_req; +input ma_ack; + +// Register File interface +output rf_re; +output rf_we; +input [31:0] rf_din; +output [31:0] rf_dout; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [5:0] // synopsys enum state + IDLE = 6'b00_0001, + MA_WR = 6'b00_0010, + MA_RD = 6'b00_0100, + W0 = 6'b00_1000, + W1 = 6'b01_0000, + W2 = 6'b10_0000; + +reg [5:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg wb_req_s1; +reg wb_ack_d, wb_ack_s1, wb_ack_s1a, wb_ack_s2; +reg ma_we; +reg rf_re, rf_we_d; +reg ma_req; +reg wb_ack_o; +reg [31:0] wb_data_o; + +/////////////////////////////////////////////////////////////////// +// +// Interface Logic +// + +assign ma_adr = wb_addr_i; +assign ma_dout = wb_data_i; +assign rf_dout = wb_data_i; + +always @(posedge wb_clk) + if( `USBF_RF_SEL ) wb_data_o <= rf_din; + else wb_data_o <= ma_din; + +// Sync WISHBONE Request +always @(posedge phy_clk) + wb_req_s1 <= wb_stb_i & wb_cyc_i; + +// Sync WISHBONE Ack +always @(posedge wb_clk) + wb_ack_s1 <= wb_ack_d; + +always @(posedge wb_clk) + wb_ack_o <= wb_ack_s1 & !wb_ack_s2 & !wb_ack_o; + +always @(posedge wb_clk) + wb_ack_s1a <= wb_ack_s1; + +always @(posedge wb_clk) + wb_ack_s2 <= wb_ack_s1a; + +assign rf_we = rf_we_d; + +/////////////////////////////////////////////////////////////////// +// +// Interface State Machine +// + +`ifdef USBF_ASYNC_RESET +always @(posedge phy_clk or negedge rst) +`else +always @(posedge phy_clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or wb_req_s1 or wb_addr_i or ma_ack or wb_we_i) + begin + next_state = state; + ma_req = 1'b0; + ma_we = 1'b0; + wb_ack_d = 1'b0; + rf_re = 1'b0; + rf_we_d = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + begin + if(wb_req_s1 && `USBF_MEM_SEL && wb_we_i) + begin + ma_req = 1'b1; + ma_we = 1'b1; + next_state = MA_WR; + end + if(wb_req_s1 && `USBF_MEM_SEL && !wb_we_i) + begin + ma_req = 1'b1; + next_state = MA_RD; + end + if(wb_req_s1 && `USBF_RF_SEL && wb_we_i) + begin + rf_we_d = 1'b1; + next_state = W0; + end + if(wb_req_s1 && `USBF_RF_SEL && !wb_we_i) + begin + rf_re = 1'b1; + next_state = W0; + end + end + + MA_WR: + begin + if(!ma_ack) + begin + ma_req = 1'b1; + ma_we = 1'b1; + end + else + begin + wb_ack_d = 1'b1; + next_state = W1; + end + end + + MA_RD: + begin + if(!ma_ack) + begin + ma_req = 1'b1; + end + else + begin + wb_ack_d = 1'b1; + next_state = W1; + end + end + + W0: + begin + wb_ack_d = 1'b1; + next_state = W1; + end + + W1: + begin + next_state = W2; + end + + W2: + begin + next_state = IDLE; + end + + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v new file mode 100644 index 000000000..ff9e265a8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v new file mode 100644 index 000000000..4ee345add --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v @@ -0,0 +1,184 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_phy.v,v 1.4 2003/10/21 05:58:40 rudi Exp $ +// +// $Date: 2003/10/21 05:58:40 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_phy.v,v $ +// Revision 1.4 2003/10/21 05:58:40 rudi +// usb_rst is no longer or'ed with the incomming reset internally. +// Now usb_rst is simply an output, the application can decide how +// to utilize it. +// +// Revision 1.3 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.2 2002/09/16 16:06:37 rudi +// Changed top level name to be consistent ... +// +// Revision 1.1.1.1 2002/09/16 14:26:59 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_phy(clk, rst, phy_tx_mode, usb_rst, + + // Transciever Interface + txdp, txdn, txoe, + rxd, rxdp, rxdn, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o, RxValid_o, + RxActive_o, RxError_o, DataIn_o, LineState_o + ); + +input clk; +input rst; +input phy_tx_mode; +output usb_rst; +output txdp, txdn, txoe; +input rxd, rxdp, rxdn; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +output [1:0] LineState_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [4:0] rst_cnt; +reg usb_rst; +wire fs_ce; +wire rst; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +/////////////////////////////////////////////////////////////////// +// +// TX Phy +// + +usb_tx_phy i_tx_phy( + .clk( clk ), + .rst( rst ), + .fs_ce( fs_ce ), + .phy_mode( phy_tx_mode ), + + // Transciever Interface + .txdp( txdp ), + .txdn( txdn ), + .txoe( txoe ), + + // UTMI Interface + .DataOut_i( DataOut_i ), + .TxValid_i( TxValid_i ), + .TxReady_o( TxReady_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// RX Phy and DPLL +// + +usb_rx_phy i_rx_phy( + .clk( clk ), + .rst( rst ), + .fs_ce( fs_ce ), + + // Transciever Interface + .rxd( rxd ), + .rxdp( rxdp ), + .rxdn( rxdn ), + + // UTMI Interface + .DataIn_o( DataIn_o ), + .RxValid_o( RxValid_o ), + .RxActive_o( RxActive_o ), + .RxError_o( RxError_o ), + .RxEn_i( txoe ), + .LineState( LineState_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// Generate an USB Reset is we see SE0 for at least 2.5uS +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rst_cnt <= 5'h0; + else + if(LineState_o != 2'h0) rst_cnt <= 5'h0; + else + if(!usb_rst && fs_ce) rst_cnt <= rst_cnt + 5'h1; + +always @(posedge clk) + usb_rst <= (rst_cnt == 5'h1f); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v new file mode 100644 index 000000000..c0568fb7d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v @@ -0,0 +1,452 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// RX & DPLL //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_rx_phy.v,v 1.5 2004/10/19 09:29:07 rudi Exp $ +// +// $Date: 2004/10/19 09:29:07 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_rx_phy.v,v $ +// Revision 1.5 2004/10/19 09:29:07 rudi +// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted). +// +// Revision 1.4 2003/12/02 04:56:00 rudi +// Fixed a bug reported by Karl C. Posch from Graz University of Technology. Thanks Karl ! +// +// Revision 1.3 2003/10/19 18:07:45 rudi +// - Fixed Sync Error to be only checked/generated during the sync phase +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:01 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_rx_phy( clk, rst, fs_ce, + + // Transciever Interface + rxd, rxdp, rxdn, + + // UTMI Interface + RxValid_o, RxActive_o, RxError_o, DataIn_o, + RxEn_i, LineState); + +input clk; +input rst; +output fs_ce; +input rxd, rxdp, rxdn; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +input RxEn_i; +output [1:0] LineState; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg rxd_s0, rxd_s1, rxd_s; +reg rxdp_s0, rxdp_s1, rxdp_s, rxdp_s_r; +reg rxdn_s0, rxdn_s1, rxdn_s, rxdn_s_r; +reg synced_d; +wire k, j, se0; +reg rxd_r; +reg rx_en; +reg rx_active; +reg [2:0] bit_cnt; +reg rx_valid1, rx_valid; +reg shift_en; +reg sd_r; +reg sd_nrzi; +reg [7:0] hold_reg; +wire drop_bit; // Indicates a stuffed bit +reg [2:0] one_cnt; + +reg [1:0] dpll_state, dpll_next_state; +reg fs_ce_d; +reg fs_ce; +wire change; +wire lock_en; +reg [2:0] fs_state, fs_next_state; +reg rx_valid_r; +reg sync_err_d, sync_err; +reg bit_stuff_err; +reg se0_r, byte_err; +reg se0_s; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign RxActive_o = rx_active; +assign RxValid_o = rx_valid; +assign RxError_o = sync_err | bit_stuff_err | byte_err; +assign DataIn_o = hold_reg; +assign LineState = {rxdn_s1, rxdp_s1}; + +always @(posedge clk) rx_en <= RxEn_i; +always @(posedge clk) sync_err <= !rx_active & sync_err_d; + +/////////////////////////////////////////////////////////////////// +// +// Synchronize Inputs +// + +// First synchronize to the local system clock to +// avoid metastability outside the sync block (*_s0). +// Then make sure we see the signal for at least two +// clock cycles stable to avoid glitches and noise + +always @(posedge clk) rxd_s0 <= rxd; +always @(posedge clk) rxd_s1 <= rxd_s0; +always @(posedge clk) // Avoid detecting Line Glitches and noise + if(rxd_s0 && rxd_s1) rxd_s <= 1'b1; + else + if(!rxd_s0 && !rxd_s1) rxd_s <= 1'b0; + +always @(posedge clk) rxdp_s0 <= rxdp; +always @(posedge clk) rxdp_s1 <= rxdp_s0; +always @(posedge clk) rxdp_s_r <= rxdp_s0 & rxdp_s1; +always @(posedge clk) rxdp_s <= (rxdp_s0 & rxdp_s1) | rxdp_s_r; // Avoid detecting Line Glitches and noise + +always @(posedge clk) rxdn_s0 <= rxdn; +always @(posedge clk) rxdn_s1 <= rxdn_s0; +always @(posedge clk) rxdn_s_r <= rxdn_s0 & rxdn_s1; +always @(posedge clk) rxdn_s <= (rxdn_s0 & rxdn_s1) | rxdn_s_r; // Avoid detecting Line Glitches and noise + +assign k = !rxdp_s & rxdn_s; +assign j = rxdp_s & !rxdn_s; +assign se0 = !rxdp_s & !rxdn_s; + +always @(posedge clk) if(fs_ce) se0_s <= se0; + +/////////////////////////////////////////////////////////////////// +// +// DPLL +// + +// This design uses a clock enable to do 12Mhz timing and not a +// real 12Mhz clock. Everything always runs at 48Mhz. We want to +// make sure however, that the clock enable is always exactly in +// the middle between two virtual 12Mhz rising edges. +// We monitor rxdp and rxdn for any changes and do the appropiate +// adjustments. +// In addition to the locking done in the dpll FSM, we adjust the +// final latch enable to compensate for various sync registers ... + +// Allow lockinf only when we are receiving +assign lock_en = rx_en; + +always @(posedge clk) rxd_r <= rxd_s; + +// Edge detector +assign change = rxd_r != rxd_s; + +// DPLL FSM +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) dpll_state <= 2'h1; + else dpll_state <= dpll_next_state; + +always @(dpll_state or lock_en or change) + begin + fs_ce_d = 1'b0; + case(dpll_state) // synopsys full_case parallel_case + 2'h0: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h1; + 2'h1:begin + fs_ce_d = 1'b1; + if(lock_en && change) dpll_next_state = 2'h3; + else dpll_next_state = 2'h2; + end + 2'h2: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h3; + 2'h3: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h0; + endcase + end + +// Compensate for sync registers at the input - allign full speed +// clock enable to be in the middle between two bit changes ... +reg fs_ce_r1, fs_ce_r2; + +always @(posedge clk) fs_ce_r1 <= fs_ce_d; +always @(posedge clk) fs_ce_r2 <= fs_ce_r1; +always @(posedge clk) fs_ce <= fs_ce_r2; + + +/////////////////////////////////////////////////////////////////// +// +// Find Sync Pattern FSM +// + +parameter FS_IDLE = 3'h0, + K1 = 3'h1, + J1 = 3'h2, + K2 = 3'h3, + J2 = 3'h4, + K3 = 3'h5, + J3 = 3'h6, + K4 = 3'h7; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) fs_state <= FS_IDLE; + else fs_state <= fs_next_state; + +always @(fs_state or fs_ce or k or j or rx_en or rx_active or se0 or se0_s) + begin + synced_d = 1'b0; + sync_err_d = 1'b0; + fs_next_state = fs_state; + if(fs_ce && !rx_active && !se0 && !se0_s) + case(fs_state) // synopsys full_case parallel_case + FS_IDLE: + begin + if(k && rx_en) fs_next_state = K1; + end + K1: + begin + if(j && rx_en) fs_next_state = J1; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J1: + begin + if(k && rx_en) fs_next_state = K2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K2: + begin + if(j && rx_en) fs_next_state = J2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J2: + begin + if(k && rx_en) fs_next_state = K3; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K3: + begin + if(j && rx_en) fs_next_state = J3; + else + if(k && rx_en) + begin + fs_next_state = FS_IDLE; // Allow missing first K-J + synced_d = 1'b1; + end + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J3: + begin + if(k && rx_en) fs_next_state = K4; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K4: + begin + if(k) synced_d = 1'b1; + fs_next_state = FS_IDLE; + end + endcase + end + +/////////////////////////////////////////////////////////////////// +// +// Generate RxActive +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rx_active <= 1'b0; + else + if(synced_d && rx_en) rx_active <= 1'b1; + else + if(se0 && rx_valid_r) rx_active <= 1'b0; + +always @(posedge clk) + if(rx_valid) rx_valid_r <= 1'b1; + else + if(fs_ce) rx_valid_r <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// NRZI Decoder +// + +always @(posedge clk) + if(fs_ce) sd_r <= rxd_s; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_nrzi <= 1'b0; + else + if(!rx_active) sd_nrzi <= 1'b1; + else + if(rx_active && fs_ce) sd_nrzi <= !(rxd_s ^ sd_r); + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuff Detect +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) one_cnt <= 3'h0; + else + if(!shift_en) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_nrzi || drop_bit) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign drop_bit = (one_cnt==3'h6); + +always @(posedge clk) bit_stuff_err <= drop_bit & sd_nrzi & fs_ce & !se0 & rx_active; // Bit Stuff Error + +/////////////////////////////////////////////////////////////////// +// +// Serial => Parallel converter +// + +always @(posedge clk) + if(fs_ce) shift_en <= synced_d | rx_active; + +always @(posedge clk) + if(fs_ce && shift_en && !drop_bit) + hold_reg <= {sd_nrzi, hold_reg[7:1]}; + +/////////////////////////////////////////////////////////////////// +// +// Generate RxValid +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) bit_cnt <= 3'b0; + else + if(!shift_en) bit_cnt <= 3'h0; + else + if(fs_ce && !drop_bit) bit_cnt <= bit_cnt + 3'h1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rx_valid1 <= 1'b0; + else + if(fs_ce && !drop_bit && (bit_cnt==3'h7)) rx_valid1 <= 1'b1; + else + if(rx_valid1 && fs_ce && !drop_bit) rx_valid1 <= 1'b0; + +always @(posedge clk) rx_valid <= !drop_bit & rx_valid1 & fs_ce; + +always @(posedge clk) se0_r <= se0; + +always @(posedge clk) byte_err <= se0 & !se0_r & (|bit_cnt[2:1]) & rx_active; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v new file mode 100644 index 000000000..7f61ffd3b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v @@ -0,0 +1,465 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// TX //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_tx_phy.v,v 1.4 2004/10/19 09:29:07 rudi Exp $ +// +// $Date: 2004/10/19 09:29:07 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_tx_phy.v,v $ +// Revision 1.4 2004/10/19 09:29:07 rudi +// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted). +// +// Revision 1.3 2003/10/21 05:58:41 rudi +// usb_rst is no longer or'ed with the incomming reset internally. +// Now usb_rst is simply an output, the application can decide how +// to utilize it. +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:02 rudi +// Created Directory Structure +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_tx_phy( + clk, rst, fs_ce, phy_mode, + + // Transciever Interface + txdp, txdn, txoe, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o + ); + +input clk; +input rst; +input fs_ce; +input phy_mode; +output txdp, txdn, txoe; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter IDLE = 3'd0, + SOP = 3'h1, + DATA = 3'h2, + EOP1 = 3'h3, + EOP2 = 3'h4, + WAIT = 3'h5; + +reg TxReady_o; +reg [2:0] state, next_state; +reg tx_ready_d; +reg ld_sop_d; +reg ld_data_d; +reg ld_eop_d; +reg tx_ip; +reg tx_ip_sync; +reg [2:0] bit_cnt; +reg [7:0] hold_reg; +reg [7:0] hold_reg_d; + +reg sd_raw_o; +wire hold; +reg data_done; +reg sft_done; +reg sft_done_r; +wire sft_done_e; +reg ld_data; +wire eop_done; +reg [2:0] one_cnt; +wire stuff; +reg sd_bs_o; +reg sd_nrzi_o; +reg append_eop; +reg append_eop_sync1; +reg append_eop_sync2; +reg append_eop_sync3; +reg append_eop_sync4; +reg txdp, txdn; +reg txoe_r1, txoe_r2; +reg txoe; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) TxReady_o <= 1'b0; + else TxReady_o <= tx_ready_d & TxValid_i; + +always @(posedge clk) ld_data <= ld_data_d; + +/////////////////////////////////////////////////////////////////// +// +// Transmit in progress indicator +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) tx_ip <= 1'b0; + else + if(ld_sop_d) tx_ip <= 1'b1; + else + if(eop_done) tx_ip <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) tx_ip_sync <= 1'b0; + else + if(fs_ce) tx_ip_sync <= tx_ip; + +// data_done helps us to catch cases where TxValid drops due to +// packet end and then gets re-asserted as a new packet starts. +// We might not see this because we are still transmitting. +// data_done should solve those cases ... +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) data_done <= 1'b0; + else + if(TxValid_i && ! tx_ip) data_done <= 1'b1; + else + if(!TxValid_i) data_done <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// Shift Register +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) bit_cnt <= 3'h0; + else + if(!tx_ip_sync) bit_cnt <= 3'h0; + else + if(fs_ce && !hold) bit_cnt <= bit_cnt + 3'h1; + +assign hold = stuff; + +always @(posedge clk) + if(!tx_ip_sync) sd_raw_o <= 1'b0; + else + case(bit_cnt) // synopsys full_case parallel_case + 3'h0: sd_raw_o <= hold_reg_d[0]; + 3'h1: sd_raw_o <= hold_reg_d[1]; + 3'h2: sd_raw_o <= hold_reg_d[2]; + 3'h3: sd_raw_o <= hold_reg_d[3]; + 3'h4: sd_raw_o <= hold_reg_d[4]; + 3'h5: sd_raw_o <= hold_reg_d[5]; + 3'h6: sd_raw_o <= hold_reg_d[6]; + 3'h7: sd_raw_o <= hold_reg_d[7]; + endcase + +always @(posedge clk) + sft_done <= !hold & (bit_cnt == 3'h7); + +always @(posedge clk) + sft_done_r <= sft_done; + +assign sft_done_e = sft_done & !sft_done_r; + +// Out Data Hold Register +always @(posedge clk) + if(ld_sop_d) hold_reg <= 8'h80; + else + if(ld_data) hold_reg <= DataOut_i; + +always @(posedge clk) hold_reg_d <= hold_reg; + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuffer +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) one_cnt <= 3'h0; + else + if(!tx_ip_sync) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_raw_o || stuff) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign stuff = (one_cnt==3'h6); + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_bs_o <= 1'h0; + else + if(fs_ce) sd_bs_o <= !tx_ip_sync ? 1'b0 : (stuff ? 1'b0 : sd_raw_o); + +/////////////////////////////////////////////////////////////////// +// +// NRZI Encoder +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_nrzi_o <= 1'b1; + else + if(!tx_ip_sync || !txoe_r1) sd_nrzi_o <= 1'b1; + else + if(fs_ce) sd_nrzi_o <= sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o; + +/////////////////////////////////////////////////////////////////// +// +// EOP append logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop <= 1'b0; + else + if(ld_eop_d) append_eop <= 1'b1; + else + if(append_eop_sync2) append_eop <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync1 <= 1'b0; + else + if(fs_ce) append_eop_sync1 <= append_eop; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync2 <= 1'b0; + else + if(fs_ce) append_eop_sync2 <= append_eop_sync1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync3 <= 1'b0; + else + if(fs_ce) append_eop_sync3 <= append_eop_sync2 | + (append_eop_sync3 & !append_eop_sync4); // Make sure always 2 bit wide + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync4 <= 1'b0; + else + if(fs_ce) append_eop_sync4 <= append_eop_sync3; + +assign eop_done = append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Output Enable Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe_r1 <= 1'b0; + else + if(fs_ce) txoe_r1 <= tx_ip_sync; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe_r2 <= 1'b0; + else + if(fs_ce) txoe_r2 <= txoe_r1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe <= 1'b1; + else + if(fs_ce) txoe <= !(txoe_r1 | txoe_r2); + +/////////////////////////////////////////////////////////////////// +// +// Output Registers +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txdp <= 1'b1; + else + if(fs_ce) txdp <= phy_mode ? + (!append_eop_sync3 & sd_nrzi_o) : + sd_nrzi_o; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txdn <= 1'b0; + else + if(fs_ce) txdn <= phy_mode ? + (!append_eop_sync3 & ~sd_nrzi_o) : + append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Tx Statemashine +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce) + begin + next_state = state; + tx_ready_d = 1'b0; + + ld_sop_d = 1'b0; + ld_data_d = 1'b0; + ld_eop_d = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + if(TxValid_i) + begin + ld_sop_d = 1'b1; + next_state = SOP; + end + SOP: + if(sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + next_state = DATA; + end + DATA: + begin + if(!data_done && sft_done_e) + begin + ld_eop_d = 1'b1; + next_state = EOP1; + end + + if(data_done && sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + end + end + EOP1: + if(eop_done) next_state = EOP2; + EOP2: + if(!eop_done && fs_ce) next_state = WAIT; + WAIT: + if(fs_ce) next_state = IDLE; + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v new file mode 100644 index 000000000..7016af86d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v @@ -0,0 +1,515 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Generic Dual-Port Synchronous RAM //// +//// //// +//// This file is part of memory library available from //// +//// http://www.opencores.org/cvsweb.shtml/generic_memories/ //// +//// //// +//// Description //// +//// This block is a wrapper with common dual-port //// +//// synchronous memory interface for different //// +//// types of ASIC and FPGA RAMs. Beside universal memory //// +//// interface it also provides behavioral model of generic //// +//// dual-port synchronous RAM. //// +//// It also contains a fully synthesizeable model for FPGAs. //// +//// It should be used in all OPENCORES designs that want to be //// +//// portable accross different target technologies and //// +//// independent of target memory. //// +//// //// +//// Supported ASIC RAMs are: //// +//// - Artisan Dual-Port Sync RAM //// +//// - Avant! Two-Port Sync RAM (*) //// +//// - Virage 2-port Sync RAM //// +//// //// +//// Supported FPGA RAMs are: //// +//// - Generic FPGA (VENDOR_FPGA) //// +//// Tested RAMs: Altera, Xilinx //// +//// Synthesis tools: LeonardoSpectrum, Synplicity //// +//// - Xilinx (VENDOR_XILINX) //// +//// - Altera (VENDOR_ALTERA) //// +//// //// +//// To Do: //// +//// - fix Avant! //// +//// - add additional RAMs (VS etc) //// +//// //// +//// Author(s): //// +//// - Richard Herveille, richard@asics.ws //// +//// - Damjan Lampret, lampret@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: generic_dpram.v,v $ +// Revision 1.3 2003/03/18 21:45:48 rherveille +// Added WISHBONE revB.3 Registered Feedback Cycles support +// +// Revision 1.4 2002/09/28 08:18:52 rherveille +// Changed synthesizeable FPGA memory implementation. +// Fixed some issues with Xilinx BlockRAM +// +// Revision 1.3 2001/11/09 00:34:18 samg +// minor changes: unified with all common rams +// +// Revision 1.2 2001/11/08 19:11:31 samg +// added valid checks to behvioral model +// +// Revision 1.1.1.1 2001/09/14 09:57:10 rherveille +// Major cleanup. +// Files are now compliant to Altera & Xilinx memories. +// Memories are now compatible, i.e. drop-in replacements. +// Added synthesizeable generic FPGA description. +// Created "generic_memories" cvs entry. +// +// Revision 1.1.1.2 2001/08/21 13:09:27 damjan +// *** empty log message *** +// +// Revision 1.1 2001/08/20 18:23:20 damjan +// Initial revision +// +// Revision 1.1 2001/08/09 13:39:33 lampret +// Major clean-up. +// +// Revision 1.2 2001/07/30 05:38:02 lampret +// Adding empty directories required by HDL coding guidelines +// +// + +//synopsys translate_off +`include "timescale.v" +//synopsys translate_on + +`define VENDOR_FPGA +//`define VENDOR_XILINX +//`define VENDOR_ALTERA + +module generic_dpram( + // Generic synchronous dual-port RAM interface + rclk, rrst, rce, oe, raddr, do, + wclk, wrst, wce, we, waddr, di +); + + // + // Default address and data buses width + // + parameter aw = 5; // number of bits in address-bus + parameter dw = 16; // number of bits in data-bus + + // + // Generic synchronous double-port RAM interface + // + // read port + input rclk; // read clock, rising edge trigger + input rrst; // read port reset, active high + input rce; // read port chip enable, active high + input oe; // output enable, active high + input [aw-1:0] raddr; // read address + output [dw-1:0] do; // data output + + // write port + input wclk; // write clock, rising edge trigger + input wrst; // write port reset, active high + input wce; // write port chip enable, active high + input we; // write enable, active high + input [aw-1:0] waddr; // write address + input [dw-1:0] di; // data input + + // + // Module body + // + +`ifdef VENDOR_FPGA + // + // Instantiation synthesizeable FPGA memory + // + // This code has been tested using LeonardoSpectrum and Synplicity. + // The code correctly instantiates Altera EABs and Xilinx BlockRAMs. + // + + // NOTE: + // 'synthesis syn_ramstyle="block_ram"' is a Synplify attribute. + // It instructs Synplify to map to BlockRAMs instead of the default SelectRAMs + + reg [dw-1:0] mem [(1<= cursor_x) && (xcnt < (cursor_x + (cursor_res ? 16'h7f : 16'h1f) )); + inbox_y <= #1 (ycnt >= cursor_y) && (ycnt < (cursor_y + (cursor_res ? 16'h7f : 16'h1f) )); + end + + assign inbox = inbox_x && inbox_y; + + always@(posedge clk) + dinbox <= #1 inbox; + + always@(posedge clk) + if (didat_wreq) + ddinbox <= #1 dinbox; + + always@(posedge clk) + dddinbox <= #1 ddinbox; + + // + // generate cursor buffer address counter + always@(posedge clk) + if (!cursor_en || ydone) + cbuf_ra <= #1 12'h0; + else if (inbox && idat_wreq) + cbuf_ra <= #1 cbuf_ra +12'h1; + + always@(posedge clk) + dcbuf_ra <= #1 cbuf_ra[2:0]; + + assign cbuf_a = cursor_we ? cursor_wadr : cursor_res ? cbuf_ra[11:3] : cbuf_ra[9:1]; + + // hookup local cursor memory (generic synchronous single port memory) + // cursor memory should never be written to/read from at the same time + generic_spram #(9, 32) cbuf( + .clk(clk), + .rst(1'b0), // no reset + .ce(1'b1), // always enable memory + .we(cursor_we), + .oe(1'b1), // always output data + .addr(cbuf_a), + .di(cursor_wdat), + .do(cbuf_q) + ); + + // + // decode cursor data for 32x32x16bpp mode + always@(posedge clk) + if (didat_wreq) + cdat <= #1 dcbuf_ra[0] ? cbuf_q[31:16] : cbuf_q[15:0]; + + always@(posedge clk) + dcdat <= #1 cdat; + + // + // decode cursor data for 64x64x4bpp mode + + // generate cursor-color address + always@(posedge clk) + if (didat_wreq) + case (dcbuf_ra) + 3'b000: cc_adr_o <= cbuf_q[ 3: 0]; + 3'b001: cc_adr_o <= cbuf_q[ 7: 4]; + 3'b010: cc_adr_o <= cbuf_q[11: 8]; + 3'b011: cc_adr_o <= cbuf_q[15:12]; + 3'b100: cc_adr_o <= cbuf_q[19:16]; + 3'b101: cc_adr_o <= cbuf_q[23:20]; + 3'b110: cc_adr_o <= cbuf_q[27:24]; + 3'b111: cc_adr_o <= cbuf_q[31:28]; + endcase + + // + // generate cursor colors + assign cursor_isalpha = cursor_res ? cc_dat_i[15] : dcdat[15]; + assign cursor_alpha = cursor_res ? cc_dat_i[7:0] : dcdat[7:0]; + assign cursor_r = {cursor_res ? cc_dat_i[14:10] : dcdat[14:10], 3'h0}; + assign cursor_g = {cursor_res ? cc_dat_i[ 9: 5] : dcdat[ 9: 5], 3'h0}; + assign cursor_b = {cursor_res ? cc_dat_i[ 4: 0] : dcdat[ 4: 0], 3'h0}; + + // + // delay image data + always@(posedge clk) + didat <= #1 idat; + + always@(posedge clk) + if (didat_wreq) + ddidat <= #1 didat; + + always@(posedge clk) + dddidat <= #1 ddidat; + + always@(posedge clk) + begin + didat_wreq <= #1 idat_wreq; + ddidat_wreq <= #1 didat_wreq; + end + + // + // generate selection unit + always@(posedge clk) + dcursor_en <= #1 cursor_en; + + always@(posedge clk) + if (didat_wreq) + ddcursor_en <= #1 dcursor_en; + + always@(posedge clk) + dddcursor_en <= #1 ddcursor_en; + + // Alpha blending: + // rgb = (rgb1 * alhpa1) + (rgb2 * alpha2) + // We generate an alpha mixer (alpha1 + alpha2 = 1) + // rgb = (alpha1)(rgb1) + (1-alpha1)(rgb2) + // We always mix to black (rgb2 = 0) + // rgb = (alpha1)(rgb1) + always@(posedge clk) + if (ddidat_wreq) + if (!dddcursor_en || !dddinbox) + rgb <= #1 dddidat; + else if (cursor_isalpha) + `ifdef VGA_HWC_3D + rgb <= #1 dddidat * cursor_alpha; + `else + rgb <= #1 dddidat; + `endif + else + rgb <= #1 {cursor_r, cursor_g, cursor_b}; + + // + // generate write request signal + always@(posedge clk) + if (rst_i) + begin + store1 <= #1 1'b0; + store2 <= #1 1'b0; + end + else + begin + store1 <= #1 didat_wreq | store1; + store2 <= #1 (didat_wreq & store1) | store2; + end + + // skip 2 idat_wreq signal, to keep in pace with rgb_fifo_full signal + always@(posedge clk) + rgb_fifo_wreq <= #1 ddidat_wreq & store2; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v new file mode 100644 index 000000000..727c21870 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant enhanced VGA/LCD Core //// +//// Defines file //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/vga_lcd //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: vga_defines.v,v 1.6 2003/08/01 11:46:38 rherveille Exp $ +// +// $Date: 2003/08/01 11:46:38 $ +// $Revision: 1.6 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: vga_defines.v,v $ +// Revision 1.6 2003/08/01 11:46:38 rherveille +// 1) Rewrote vga_fifo_dc. It now uses gray codes and a more elaborate anti-metastability scheme. +// 2) Changed top level and pixel generator to reflect changes in the fifo. +// 3) Changed a bug in vga_fifo. +// 4) Changed pixel generator and wishbone master to reflect changes. +// +// Revision 1.5 2003/05/07 09:48:54 rherveille +// Fixed some Wishbone RevB.3 related bugs. +// Changed layout of the core. Blocks are located more logically now. +// Started work on a dual clocked/double edge 12bit output. Commonly used by external devices like DVI transmitters. +// +// Revision 1.4 2002/02/07 05:42:10 rherveille +// Fixed some bugs discovered by modified testbench +// Removed / Changed some strange logic constructions +// Started work on hardware cursor support (not finished yet) +// Changed top-level name to vga_enh_top.v +// + + +//////////////////////// +// +// Global settings +// + +// +// define memory vendor +// for FPGA implementations use `define VENDOR_FPGA + +`define VENDOR_FPGA + +// +// enable / disable 12bit DVI output +// (for use with external DVI transmitters) +//`define VGA_12BIT_DVI + + +//////////////////////// +// +// Hardware Cursors +// + +// +// enable / disable hardware cursors +// +//`define VGA_HWC0 +//`define VGA_HWC1 + + +// +// enable / disabled 3D support for hardware cursors +// +//`define VGA_HWC_3D + diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v new file mode 100644 index 000000000..f1bf24db0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v @@ -0,0 +1,448 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant Enhanced VGA/LCD Core //// +//// Top Level //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/vga_lcd //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001,2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: vga_enh_top.v,v 1.6 2003/08/01 11:46:38 rherveille Exp $ +// +// $Date: 2003/08/01 11:46:38 $ +// $Revision: 1.6 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: vga_enh_top.v,v $ +// Revision 1.6 2003/08/01 11:46:38 rherveille +// 1) Rewrote vga_fifo_dc. It now uses gray codes and a more elaborate anti-metastability scheme. +// 2) Changed top level and pixel generator to reflect changes in the fifo. +// 3) Changed a bug in vga_fifo. +// 4) Changed pixel generator and wishbone master to reflect changes. +// +// Revision 1.5 2003/07/03 15:09:06 rherveille +// Removed 'or negedge arst' from sluint/luint sensitivity list +// +// Revision 1.4 2003/05/07 09:48:54 rherveille +// Fixed some Wishbone RevB.3 related bugs. +// Changed layout of the core. Blocks are located more logically now. +// Started work on a dual clocked/double edge 12bit output. Commonly used by external devices like DVI transmitters. +// +// Revision 1.3 2003/03/18 21:45:48 rherveille +// Added WISHBONE revB.3 Registered Feedback Cycles support +// +// Revision 1.2 2002/03/04 11:01:59 rherveille +// Added 64x64pixels 4bpp hardware cursor support. +// +// Revision 1.1 2002/02/07 05:42:10 rherveille +// Fixed some bugs discovered by modified testbench +// Removed / Changed some strange logic constructions +// Started work on hardware cursor support (not finished yet) +// Changed top-level name to vga_enh_top.v +// + +//synopsys translate_off +`include "timescale.v" +//synopsys translate_on +`include "vga_defines.v" + +module vga_enh_top ( + wb_clk_i, wb_rst_i, rst_i, wb_inta_o, + wbs_adr_i, wbs_dat_i, wbs_dat_o, wbs_sel_i, wbs_we_i, wbs_stb_i, wbs_cyc_i, wbs_ack_o, wbs_rty_o, wbs_err_o, + wbm_adr_o, wbm_dat_i, wbm_cti_o, wbm_bte_o, wbm_sel_o, wbm_we_o, wbm_stb_o, wbm_cyc_o, wbm_ack_i, wbm_err_i, + clk_p_i, +`ifdef VGA_12BIT_DVI + dvi_pclk_p_o, dvi_pclk_m_o, dvi_hsync_o, dvi_vsync_o, dvi_de_o, dvi_d_o, +`endif + clk_p_o, hsync_pad_o, vsync_pad_o, csync_pad_o, blank_pad_o, r_pad_o, g_pad_o, b_pad_o + ); + + // + // parameters + // + parameter ARST_LVL = 1'b0; + parameter LINE_FIFO_AWIDTH = 7; + + // + // inputs & outputs + // + + // syscon interface + input wb_clk_i; // wishbone clock input + input wb_rst_i; // synchronous active high reset + input rst_i; // asynchronous reset + output wb_inta_o; // interrupt request output + + // slave signals + input [11:0] wbs_adr_i; // addressbus input (only 32bit databus accesses supported) + input [31:0] wbs_dat_i; // Slave databus output + output [31:0] wbs_dat_o; // Slave databus input + input [ 3:0] wbs_sel_i; // byte select inputs + input wbs_we_i; // write enabel input + input wbs_stb_i; // strobe/select input + input wbs_cyc_i; // valid bus cycle input + output wbs_ack_o; // bus cycle acknowledge output + output wbs_rty_o; // busy cycle retry output + output wbs_err_o; // bus cycle error output + + // master signals + output [31:0] wbm_adr_o; // addressbus output + input [31:0] wbm_dat_i; // Master databus input + output [ 3:0] wbm_sel_o; // byte select outputs + output wbm_we_o; // write enable output + output wbm_stb_o; // strobe output + output wbm_cyc_o; // valid bus cycle output + output [ 2:0] wbm_cti_o; // cycle type identifier + output [ 1:0] wbm_bte_o; // burst type extensions + input wbm_ack_i; // bus cycle acknowledge input + input wbm_err_i; // bus cycle error input + + // VGA signals + input clk_p_i; // pixel clock + // in DVI mode this is 2x as high (!!) + + `ifdef VGA_12BIT_DVI + output dvi_pclk_p_o; // dvi pclk+ + output dvi_pclk_m_o; // dvi pclk- + output dvi_hsync_o; // dvi hsync + output dvi_vsync_o; // dvi vsync + output dvi_de_o; // dvi data enable + output [11:0] dvi_d_o; // dvi 12bit output + `endif + + output clk_p_o; // VGA pixel clock output + output hsync_pad_o; // horizontal sync + output vsync_pad_o; // vertical sync + output csync_pad_o; // composite sync + output blank_pad_o; // blanking signal + output [ 7:0] r_pad_o, g_pad_o, b_pad_o; // RGB color signals + + // + // variable declarations + // + + // programable asynchronous reset + wire arst = rst_i ^ ARST_LVL; + + // from wb_slave + wire ctrl_bl, ctrl_csl, ctrl_vsl, ctrl_hsl, ctrl_pc, ctrl_cbsw, ctrl_vbsw, ctrl_ven; + wire [ 1: 0] ctrl_cd, ctrl_vbl, ctrl_dvi_odf; + wire [ 7: 0] Thsync, Thgdel, Tvsync, Tvgdel; + wire [15: 0] Thgate, Thlen, Tvgate, Tvlen; + wire [31: 2] VBARa, VBARb; + + wire [ 8: 0] cursor_adr; + wire [31: 0] cursor0_xy, cursor1_xy; + wire cursor0_en, cursor1_en; + wire [31:11] cursor0_ba, cursor1_ba; + wire cursor0_ld, cursor1_ld; + wire cursor0_res, cursor1_res; + wire [15: 0] cc0_dat_o, cc1_dat_o; + + // to wb_slave + wire stat_avmp, stat_acmp, vmem_swint, clut_swint, hint, vint, sint; + wire wmb_busy; + reg luint; + wire [ 3: 0] cc0_adr_i, cc1_adr_i; + + // pixel generator + wire fb_data_fifo_rreq, fb_data_fifo_empty; + wire [31:0] fb_data_fifo_q; + wire ImDoneFifoQ; + + // line fifo connections + wire line_fifo_wreq, line_fifo_rreq, line_fifo_empty_rd; + wire [23:0] line_fifo_d, line_fifo_q; + + // clut connections + wire ext_clut_req, ext_clut_ack; + wire [23:0] ext_clut_q; + wire cp_clut_req, cp_clut_ack; + wire [ 8:0] cp_clut_adr; + wire [23:0] cp_clut_q; + + // + // Module body + // + + // hookup wishbone slave + vga_wb_slave wbs ( + // wishbone interface + .clk_i ( wb_clk_i ), + .rst_i ( wb_rst_i ), + .arst_i ( arst ), + .adr_i ( wbs_adr_i[11:2] ), + .dat_i ( wbs_dat_i ), + .dat_o ( wbs_dat_o ), + .sel_i ( wbs_sel_i ), + .we_i ( wbs_we_i ), + .stb_i ( wbs_stb_i ), + .cyc_i ( wbs_cyc_i ), + .ack_o ( wbs_ack_o ), + .rty_o ( wbs_rty_o ), + .err_o ( wbs_err_o ), + .inta_o ( wb_inta_o ), + + // internal connections + .wbm_busy ( wbm_busy ), // Data transfer in progress + .dvi_odf ( ctrl_dvi_odf ), // DVI output data format + .bl ( ctrl_bl ), // blank polarization level + .csl ( ctrl_csl ), // csync polarization level + .vsl ( ctrl_vsl ), // vsync polarization level + .hsl ( ctrl_hsl ), // hsync polarization level + .pc ( ctrl_pc ), // pseudo-color mode (only for 8bpp) + .cd ( ctrl_cd ), // color depth + .vbl ( ctrl_vbl ), // video memory burst length + .cbsw ( ctrl_cbsw ), // color lookup table bank switch enable + .vbsw ( ctrl_vbsw ), // video bank switch enable + .ven ( ctrl_ven ), // video enable + .acmp ( stat_acmp ), // active color lookup table page + .avmp ( stat_avmp ), // active video memory page + .cursor0_res ( cursor0_res ), // cursor0 resolution + .cursor0_en ( cursor0_en ), // cursor0 enable + .cursor0_xy ( cursor0_xy ), // cursor0 (x,y) + .cursor0_ba ( cursor0_ba ), // curso0 video memory base address + .cursor0_ld ( cursor0_ld ), // reload curso0 from video memory + .cc0_adr_i ( cc0_adr_i ), // cursor0 color registers address + .cc0_dat_o ( cc0_dat_o ), // cursor0 color registers data + .cursor1_res ( cursor1_res ), // cursor1 resolution + .cursor1_en ( cursor1_en ), // cursor1 enable + .cursor1_xy ( cursor1_xy ), // cursor1 (x,y) + .cursor1_ba ( cursor1_ba ), // cursor1 video memory base address + .cursor1_ld ( cursor1_ld ), // reload cursor1 from video memory + .cc1_adr_i ( cc1_adr_i ), // cursor1 color registers address + .cc1_dat_o ( cc1_dat_o ), // cursor1 color registers data + .vbsint_in ( vmem_swint ), // video memory bank switch interrupt + .cbsint_in ( clut_swint ), // clut memory bank switch interrupt + .hint_in ( hint ), // horizontal interrupt + .vint_in ( vint ), // vertical interrupt + .luint_in ( luint ), // line fifo underrun interrupt + .sint_in ( sint ), // system-error interrupt + .Thsync ( Thsync ), + .Thgdel ( Thgdel ), + .Thgate ( Thgate ), + .Thlen ( Thlen ), + .Tvsync ( Tvsync ), + .Tvgdel ( Tvgdel ), + .Tvgate ( Tvgate ), + .Tvlen ( Tvlen ), + .VBARa ( VBARa ), + .VBARb ( VBARb ), + .clut_acc ( ext_clut_req ), + .clut_ack ( ext_clut_ack ), + .clut_q ( ext_clut_q ) + ); + + // hookup wishbone master + vga_wb_master wbm ( + // wishbone interface + .clk_i ( wb_clk_i ), + .rst_i ( wb_rst_i ), + .nrst_i ( arst ), + .cyc_o ( wbm_cyc_o ), + .stb_o ( wbm_stb_o ), + .cti_o ( wbm_cti_o ), + .bte_o ( wbm_bte_o ), + .we_o ( wbm_we_o ), + .adr_o ( wbm_adr_o ), + .sel_o ( wbm_sel_o ), + .ack_i ( wbm_ack_i ), + .err_i ( wbm_err_i ), + .dat_i ( wbm_dat_i ), + + // internal connections + .sint (sint ), + .ctrl_ven (ctrl_ven ), + .ctrl_cd (ctrl_cd ), + .ctrl_vbl (ctrl_vbl ), + .ctrl_vbsw (ctrl_vbsw ), + .busy (wbm_busy ), + .VBAa (VBARa ), + .VBAb (VBARb ), + .Thgate (Thgate ), + .Tvgate (Tvgate ), + .stat_avmp (stat_avmp ), + .vmem_switch (vmem_swint ), + .ImDoneFifoQ ( ImDoneFifoQ ), + + .cursor_adr ( cursor_adr ), + .cursor0_ba ( cursor0_ba ), // curso0 video memory base address + .cursor0_ld ( cursor0_ld ), // reload curso0 from video memory + .cursor1_ba ( cursor1_ba ), // cursor1 video memory base address + .cursor1_ld ( cursor1_ld ), // reload cursor1 from video memory + + .fb_data_fifo_rreq ( fb_data_fifo_rreq ), + .fb_data_fifo_q ( fb_data_fifo_q ), + .fb_data_fifo_empty ( fb_data_fifo_empty ) + ); + + // hookup CLUT + vga_csm_pb #(24, 9) clut_mem( + .clk_i(wb_clk_i), + + // color processor access + .req0_i(cp_clut_req), + .ack0_o(cp_clut_ack), + .adr0_i(cp_clut_adr), + .dat0_i(24'h0), + .dat0_o(cp_clut_q), + .we0_i(1'b0), // no writes + + // external access + .req1_i(ext_clut_req), + .ack1_o(ext_clut_ack), + .adr1_i(wbs_adr_i[10:2]), + .dat1_i(wbs_dat_i[23:0]), + .dat1_o(ext_clut_q), + .we1_i(wbs_we_i) + ); + + // hookup pixel and video timing generator + vga_pgen pixel_generator ( + .clk_i ( wb_clk_i ), + .ctrl_ven ( ctrl_ven ), + .ctrl_HSyncL ( ctrl_hsl ), + .Thsync ( Thsync ), + .Thgdel ( Thgdel ), + .Thgate ( Thgate ), + .Thlen ( Thlen ), + .ctrl_VSyncL ( ctrl_vsl ), + .Tvsync ( Tvsync ), + .Tvgdel ( Tvgdel ), + .Tvgate ( Tvgate ), + .Tvlen ( Tvlen ), + .ctrl_CSyncL ( ctrl_csl ), + .ctrl_BlankL ( ctrl_bl ), + .eoh ( hint ), + .eov ( vint ), + + // frame buffer data (from wbm) + .fb_data_fifo_rreq ( fb_data_fifo_rreq ), + .fb_data_fifo_q ( fb_data_fifo_q ), + .fb_data_fifo_empty ( fb_data_fifo_empty ), + .ImDoneFifoQ ( ImDoneFifoQ ), + + // clut memory signals + .stat_acmp ( stat_acmp ), + .clut_req ( cp_clut_req ), + .clut_ack ( cp_clut_ack ), + .clut_adr ( cp_clut_adr ), + .clut_q ( cp_clut_q ), + .ctrl_cbsw ( ctrl_cbsw ), + .clut_switch ( clut_swint ), + + .cursor_adr ( cursor_adr ), // cursor data address (from wbm) + .cursor0_en ( cursor0_en ), // cursor0 enable + .cursor0_res ( cursor0_res ), // cursor0 resolution + .cursor0_xy ( cursor0_xy ), // cursor0 (x,y) + .cc0_adr_o ( cc0_adr_i ), // cursor0 color registers address + .cc0_dat_i ( cc0_dat_o ), // cursor0 color registers data + .cursor1_en ( cursor1_en ), // cursor1 enable + .cursor1_res ( cursor1_res ), // cursor1 resolution + .cursor1_xy ( cursor1_xy ), // cursor1 (x,y) + .cc1_adr_o ( cc1_adr_i ), // cursor1 color registers address + .cc1_dat_i ( cc1_dat_o ), // cursor1 color registers data + + .ctrl_dvi_odf ( ctrl_dvi_odf ), + .ctrl_cd ( ctrl_cd ), + .ctrl_pc ( ctrl_pc ), + + // line fifo memory signals + .line_fifo_wreq ( line_fifo_wreq ), + .line_fifo_d ( line_fifo_d ), + .line_fifo_full ( line_fifo_full_wr ), + .line_fifo_rreq ( line_fifo_rreq ), + .line_fifo_q ( line_fifo_q ), + + .pclk_i ( clk_p_i ), + `ifdef VGA_12BIT_DVI + .dvi_pclk_p_o ( dvi_pclk_p_o ), + .dvi_pclk_m_o ( dvi_pclk_m_o ), + .dvi_hsync_o ( dvi_hsync_o ), + .dvi_vsync_o ( dvi_vsync_o ), + .dvi_de_o ( dvi_de_o ), + .dvi_d_o ( dvi_d_o ), + `endif + .pclk_o ( clk_p_o ), + .hsync_o ( hsync_pad_o ), + .vsync_o ( vsync_pad_o ), + .csync_o ( csync_pad_o ), + .blank_o ( blank_pad_o ), + .r_o ( r_pad_o ), + .g_o ( g_pad_o ), + .b_o ( b_pad_o ) + + ); + + // hookup line-fifo + wire ctrl_ven_not = ~ctrl_ven; + vga_fifo_dc #(LINE_FIFO_AWIDTH, 24) line_fifo ( + .rclk ( clk_p_i ), + .wclk ( wb_clk_i ), + .rclr ( 1'b0 ), + .wclr ( ctrl_ven_not ), + .wreq ( line_fifo_wreq ), + .d ( line_fifo_d ), + .rreq ( line_fifo_rreq ), + .q ( line_fifo_q ), + .empty ( line_fifo_empty_rd ), + .full ( line_fifo_full_wr ) + ); + + // generate interrupt signal when reading line-fifo while it is empty (line-fifo under-run interrupt) + reg luint_pclk, sluint; + + always @(posedge clk_p_i) + luint_pclk <= #1 line_fifo_rreq & line_fifo_empty_rd; + + always @(posedge wb_clk_i) + if (!ctrl_ven) + begin + sluint <= #1 1'b0; + luint <= #1 1'b0; + end + else + begin + sluint <= #1 luint_pclk; // resample at wb_clk_i clock + luint <= #1 sluint; // sample again, reduce metastability risk + end + +endmodule + + + + + diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v new file mode 100644 index 000000000..b467a621b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v @@ -0,0 +1,259 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// generic FIFO, uses LFSRs for read/write pointers //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: vga_fifo.v,v 1.8 2003/08/01 11:46:38 rherveille Exp $ +// +// $Date: 2003/08/01 11:46:38 $ +// $Revision: 1.8 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: vga_fifo.v,v $ +// Revision 1.8 2003/08/01 11:46:38 rherveille +// 1) Rewrote vga_fifo_dc. It now uses gray codes and a more elaborate anti-metastability scheme. +// 2) Changed top level and pixel generator to reflect changes in the fifo. +// 3) Changed a bug in vga_fifo. +// 4) Changed pixel generator and wishbone master to reflect changes. +// +// Revision 1.7 2003/05/07 09:48:54 rherveille +// Fixed some Wishbone RevB.3 related bugs. +// Changed layout of the core. Blocks are located more logically now. +// Started work on a dual clocked/double edge 12bit output. Commonly used by external devices like DVI transmitters. +// +// Revision 1.6 2002/02/07 05:42:10 rherveille +// Fixed some bugs discovered by modified testbench +// Removed / Changed some strange logic constructions +// Started work on hardware cursor support (not finished yet) +// Changed top-level name to vga_enh_top.v +// + +//synopsys translate_off +`include "timescale.v" +//synopsys translate_on + + +// set FIFO_RW_CHECK to prevent writing to a full and reading from an empty FIFO +//`define FIFO_RW_CHECK + +// Long Pseudo Random Generators can generate (N^2 -1) combinations. This means +// 1 FIFO entry is unavailable. This might be a problem, especially for small +// FIFOs. Setting VGA_FIFO_ALL_ENTRIES creates additional logic that ensures that +// all FIFO entries are used at the expense of some additional logic. +`define VGA_FIFO_ALL_ENTRIES + +module vga_fifo ( + clk, + aclr, + sclr, + wreq, + rreq, + d, + q, + nword, + empty, + full, + aempty, + afull + ); + + // + // parameters + // + parameter aw = 3; // no.of entries (in bits; 2^7=128 entries) + parameter dw = 8; // datawidth (in bits) + + // + // inputs & outputs + // + input clk; // master clock + input aclr; // asynchronous active low reset + input sclr; // synchronous active high reset + + input wreq; // write request + input rreq; // read request + input [dw:1] d; // data-input + output [dw:1] q; // data-output + + output [aw:0] nword; // number of words in FIFO + + output empty; // fifo empty + output full; // fifo full + + output aempty; // fifo asynchronous/almost empty (1 entry left) + output afull; // fifo asynchronous/almost full (1 entry left) + + reg [aw:0] nword; + reg empty, full; + + // + // Module body + // + reg [aw:1] rp, wp; + wire [dw:1] ramq; + wire fwreq, frreq; + +`ifdef VGA_FIFO_ALL_ENTRIES + function lsb; + input [aw:1] q; + case (aw) + 2: lsb = ~q[2]; + 3: lsb = &q[aw-1:1] ^ ~(q[3] ^ q[2]); + 4: lsb = &q[aw-1:1] ^ ~(q[4] ^ q[3]); + 5: lsb = &q[aw-1:1] ^ ~(q[5] ^ q[3]); + 6: lsb = &q[aw-1:1] ^ ~(q[6] ^ q[5]); + 7: lsb = &q[aw-1:1] ^ ~(q[7] ^ q[6]); + 8: lsb = &q[aw-1:1] ^ ~(q[8] ^ q[6] ^ q[5] ^ q[4]); + 9: lsb = &q[aw-1:1] ^ ~(q[9] ^ q[5]); + 10: lsb = &q[aw-1:1] ^ ~(q[10] ^ q[7]); + 11: lsb = &q[aw-1:1] ^ ~(q[11] ^ q[9]); + 12: lsb = &q[aw-1:1] ^ ~(q[12] ^ q[6] ^ q[4] ^ q[1]); + 13: lsb = &q[aw-1:1] ^ ~(q[13] ^ q[4] ^ q[3] ^ q[1]); + 14: lsb = &q[aw-1:1] ^ ~(q[14] ^ q[5] ^ q[3] ^ q[1]); + 15: lsb = &q[aw-1:1] ^ ~(q[15] ^ q[14]); + 16: lsb = &q[aw-1:1] ^ ~(q[16] ^ q[15] ^ q[13] ^ q[4]); + endcase + endfunction +`else + function lsb; + input [aw:1] q; + case (aw) + 2: lsb = ~q[2]; + 3: lsb = ~(q[3] ^ q[2]); + 4: lsb = ~(q[4] ^ q[3]); + 5: lsb = ~(q[5] ^ q[3]); + 6: lsb = ~(q[6] ^ q[5]); + 7: lsb = ~(q[7] ^ q[6]); + 8: lsb = ~(q[8] ^ q[6] ^ q[5] ^ q[4]); + 9: lsb = ~(q[9] ^ q[5]); + 10: lsb = ~(q[10] ^ q[7]); + 11: lsb = ~(q[11] ^ q[9]); + 12: lsb = ~(q[12] ^ q[6] ^ q[4] ^ q[1]); + 13: lsb = ~(q[13] ^ q[4] ^ q[3] ^ q[1]); + 14: lsb = ~(q[14] ^ q[5] ^ q[3] ^ q[1]); + 15: lsb = ~(q[15] ^ q[14]); + 16: lsb = ~(q[16] ^ q[15] ^ q[13] ^ q[4]); + endcase + endfunction +`endif + +`ifdef RW_CHECK + assign fwreq = wreq & ~full; + assign frreq = rreq & ~empty; +`else + assign fwreq = wreq; + assign frreq = rreq; +`endif + + // + // hookup read-pointer + // + always @(posedge clk or negedge aclr) + if (~aclr) rp <= #1 0; + else if (sclr) rp <= #1 0; + else if (frreq) rp <= #1 {rp[aw-1:1], lsb(rp)}; + + // + // hookup write-pointer + // + always @(posedge clk or negedge aclr) + if (~aclr) wp <= #1 0; + else if (sclr) wp <= #1 0; + else if (fwreq) wp <= #1 {wp[aw-1:1], lsb(wp)}; + + + // + // hookup memory-block + // + reg [dw:1] mem [(1<> 2; // 8bpp, 4 pixels per cycle + 2'b01: hgate_cnt <= #1 Thgate >> 1; // 16bpp, 2 pixels per cycle + 2'b10: hgate_cnt <= #1 Thgate >> 2; // 24bpp, 4/3 pixels per cycle + 2'b11: hgate_cnt <= #1 Thgate; // 32bpp, 1 pixel per cycle + endcase + + hgate_div_cnt <= 2'b10; + end + else if (vmem_ack) + if (hdone) + begin + case(ctrl_cd) // synopsys full_case parallel_case + 2'b00: hgate_cnt <= #1 Thgate >> 2; // 8bpp, 4 pixels per cycle + 2'b01: hgate_cnt <= #1 Thgate >> 1; // 16bpp, 2 pixels per cycle + 2'b10: hgate_cnt <= #1 Thgate >> 2; // 24bpp, 4/3 pixels per cycle + 2'b11: hgate_cnt <= #1 Thgate; // 32bpp, 1 pixel per cycle + endcase + + hgate_div_cnt <= 2'b10; + end + else //if (vmem_ack) + begin + hgate_cnt <= #1 hgate_cnt_val[15:0]; + + if ( hgate_div_val[2] ) + hgate_div_cnt <= #1 2'b10; + else + hgate_div_cnt <= #1 hgate_div_val[1:0]; + end + + // vgate counter + reg [15:0] vgate_cnt; + wire [16:0] vgate_cnt_val; + wire vdone; + + assign vgate_cnt_val = {1'b0, vgate_cnt} - 17'h1; + assign vdone = vgate_cnt_val[16]; + + always @(posedge clk_i) + if (sclr | ImDoneStrb) + vgate_cnt <= #1 Tvgate; + else if (hdone) + vgate_cnt <= #1 vgate_cnt_val[15:0]; + + assign ImDone = hdone & vdone; + + assign ImDoneStrb = ImDone & !dImDone; + + always @(posedge clk_i) + begin + dImDone <= #1 ImDone; + dImDoneStrb <= #1 ImDoneStrb; + end + + // + // generate addresses + // + + // select video memory base address + always @(posedge clk_i) + if (sclr | dImDoneStrb) + if (!sel_VBA) + vmemA <= #1 VBAa; + else + vmemA <= #1 VBAb; + else if (vmem_ack) + vmemA <= #1 vmemA +30'h1; + + + //////////////////////////////////// + // hardware cursor signals section + // + always @(posedge clk_i) + if (ImDone) + cur_acc_sel <= #1 ld_cursor0; // cursor0 has highest priority + + always @(posedge clk_i) + if (sclr) + begin + ld_cursor0 <= #1 1'b0; + ld_cursor1 <= #1 1'b0; + end + else + begin + ld_cursor0 <= #1 cursor0_ld | (ld_cursor0 & !(cur_done & cur_acc_sel)); + ld_cursor1 <= #1 cursor1_ld | (ld_cursor1 & !(cur_done & !cur_acc_sel)); + end + + // select cursor base address + always @(posedge clk_i) + if (!cur_acc) + cursor_ba <= #1 ld_cursor0 ? cursor0_ba : cursor1_ba; + + // generate pattern offset + wire [9:0] next_cursor_adr = {1'b0, cursor_adr} + 10'h1; + assign cur_done = next_cursor_adr[9] & cur_ack; + + always @(posedge clk_i) + if (!cur_acc) + cursor_adr <= #1 9'h0; + else if (cur_ack) + cursor_adr <= #1 next_cursor_adr; + + // generate cursor buffers write enable signals + assign cursor1_we = cur_ack & !cur_acc_sel; + assign cursor0_we = cur_ack & cur_acc_sel; + + + ////////////////////////////// + // generate wishbone signals + // + assign adr_o = cur_acc ? {cursor_ba, cursor_adr, 2'b00} : {vmemA, 2'b00}; + wire wb_cycle = vmem_acc & !(burst_done & vmem_ack & !vmem_req) & !ImDone || + cur_acc & !cur_done; + + always @(posedge clk_i or negedge nrst_i) + if (!nrst_i) + begin + cyc_o <= #1 1'b0; + stb_o <= #1 1'b0; + sel_o <= #1 4'b1111; + cti_o <= #1 3'b000; + bte_o <= #1 2'b00; + we_o <= #1 1'b0; + end + else + if (rst_i) + begin + cyc_o <= #1 1'b0; + stb_o <= #1 1'b0; + sel_o <= #1 4'b1111; + cti_o <= #1 3'b000; + bte_o <= #1 2'b00; + we_o <= #1 1'b0; + end + else + begin + cyc_o <= #1 wb_cycle; + stb_o <= #1 wb_cycle; + sel_o <= #1 4'b1111; // only 32bit accesses are supported + + if (wb_cycle) begin + if (cur_acc) + cti_o <= #1 &next_cursor_adr[8:0] ? 3'b111 : 3'b010; + else if (ctrl_vbl == 2'b00) + cti_o <= #1 3'b000; + else if (vmem_ack) + cti_o <= #1 (burst_cnt == 3'h1) ? 3'b111 : 3'b010; + end else + cti_o <= #1 (ctrl_vbl == 2'b00) ? 3'b000 : 3'b010; + + bte_o <= #1 2'b00; // linear burst + we_o <= #1 1'b0; // read only + end + + // + // video-data buffer (temporary store data read from video memory) + wire [4:0] fb_data_fifo_nword; +// wire fb_data_fifo_full; + + vga_fifo #(4, 32) data_fifo ( + .clk ( clk_i ), + .aclr ( 1'b1 ), + .sclr ( sclr ), + .d ( dat_i ), + .wreq ( vmem_ack ), + .q ( fb_data_fifo_q ), + .rreq ( fb_data_fifo_rreq ), + .nword ( fb_data_fifo_nword ), + .empty ( fb_data_fifo_empty ), + .full ( ),//fb_data_fifo_full ), + .aempty ( ), + .afull ( ) + ); + + assign vmem_req = ~fb_data_fifo_nword[4] & ~fb_data_fifo_nword[3]; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v new file mode 100644 index 000000000..47aad8a11 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v @@ -0,0 +1,465 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant enhanced VGA/LCD Core //// +//// Wishbone slave interface //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/vga_lcd //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: vga_wb_slave.v,v 1.12 2003/05/07 09:48:54 rherveille Exp $ +// +// $Date: 2003/05/07 09:48:54 $ +// $Revision: 1.12 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: vga_wb_slave.v,v $ +// Revision 1.12 2003/05/07 09:48:54 rherveille +// Fixed some Wishbone RevB.3 related bugs. +// Changed layout of the core. Blocks are located more logically now. +// Started work on a dual clocked/double edge 12bit output. Commonly used by external devices like DVI transmitters. +// +// Revision 1.11 2002/04/20 10:02:39 rherveille +// Changed video timing generator. +// Changed wishbone master vertical gate count code. +// Fixed a potential bug in the wishbone slave (cursor color register readout). +// +// Revision 1.10 2002/03/28 04:59:25 rherveille +// Fixed two small bugs that only showed up when the hardware cursors were disabled +// +// Revision 1.9 2002/03/04 16:05:52 rherveille +// Added hardware cursor support to wishbone master. +// Added provision to turn-off 3D cursors. +// Fixed some minor bugs. +// +// Revision 1.8 2002/03/04 11:01:59 rherveille +// Added 64x64pixels 4bpp hardware cursor support. +// +// Revision 1.7 2002/02/25 06:13:44 rherveille +// Fixed dat_o incomplete sensitivity list. +// +// Revision 1.6 2002/02/07 05:42:10 rherveille +// Fixed some bugs discovered by modified testbench +// Removed / Changed some strange logic constructions +// Started work on hardware cursor support (not finished yet) +// Changed top-level name to vga_enh_top.v +// + +//synopsys translate_off +`include "timescale.v" +//synopsys translate_on +`include "vga_defines.v" + +module vga_wb_slave( + clk_i, rst_i, arst_i, adr_i, dat_i, dat_o, sel_i, we_i, stb_i, cyc_i, ack_o, rty_o, err_o, inta_o, + wbm_busy, dvi_odf, bl, csl, vsl, hsl, pc, cd, vbl, cbsw, vbsw, ven, avmp, acmp, + cursor0_res, cursor0_en, cursor0_xy, cursor0_ba, cursor0_ld, cc0_adr_i, cc0_dat_o, + cursor1_res, cursor1_en, cursor1_xy, cursor1_ba, cursor1_ld, cc1_adr_i, cc1_dat_o, + vbsint_in, cbsint_in, hint_in, vint_in, luint_in, sint_in, + Thsync, Thgdel, Thgate, Thlen, Tvsync, Tvgdel, Tvgate, Tvlen, VBARa, VBARb, + clut_acc, clut_ack, clut_q + ); + + // + // inputs & outputs + // + + // wishbone slave interface + input clk_i; + input rst_i; + input arst_i; + input [11:2] adr_i; + input [31:0] dat_i; + output [31:0] dat_o; + reg [31:0] dat_o; + input [ 3:0] sel_i; + input we_i; + input stb_i; + input cyc_i; + output ack_o; + reg ack_o; + output rty_o; + reg rty_o; + output err_o; + reg err_o; + output inta_o; + reg inta_o; + + // wishbone master controller feedback + input wbm_busy; // data transfer in progress + + // control register settings + output [1:0] dvi_odf; // DVI output data format + output bl; // blanking level + output csl; // composite sync level + output vsl; // vsync level + output hsl; // hsync level + output pc; // pseudo color + output [1:0] cd; // color depth + output [1:0] vbl; // video memory burst length + output cbsw; // clut bank switch enable + output vbsw; // video memory bank switch enable + output ven; // video system enable + + // hardware cursor settings + output cursor0_res; // cursor0 resolution + output cursor0_en; // cursor0 enable + output [31: 0] cursor0_xy; // cursor0 location + output [31:11] cursor0_ba; // cursor0 base address + output cursor0_ld; // reload cursor0 from video memory + input [ 3: 0] cc0_adr_i; // cursor0 color register address + output [15: 0] cc0_dat_o; // cursor0 color register data + output cursor1_res; // cursor1 resolution + output cursor1_en; // cursor1 enable + output [31: 0] cursor1_xy; // cursor1 location + output [31:11] cursor1_ba; // cursor1 base address + output cursor1_ld; // reload cursor1 from video memory + input [ 3: 0] cc1_adr_i; // cursor1 color register address + output [15: 0] cc1_dat_o; // cursor1 color register data + + reg [31: 0] cursor0_xy; + reg [31:11] cursor0_ba; + reg cursor0_ld; + reg [31: 0] cursor1_xy; + reg [31:11] cursor1_ba; + reg cursor1_ld; + + // status register inputs + input avmp; // active video memory page + input acmp; // active clut memory page + input vbsint_in; // bank switch interrupt request + input cbsint_in; // clut switch interrupt request + input hint_in; // hsync interrupt request + input vint_in; // vsync interrupt request + input luint_in; // line fifo underrun interrupt request + input sint_in; // system error interrupt request + + // Horizontal Timing Register + output [ 7:0] Thsync; + output [ 7:0] Thgdel; + output [15:0] Thgate; + output [15:0] Thlen; + + // Vertical Timing Register + output [ 7:0] Tvsync; + output [ 7:0] Tvgdel; + output [15:0] Tvgate; + output [15:0] Tvlen; + + // video base addresses + output [31:2] VBARa; + reg [31:2] VBARa; + output [31:2] VBARb; + reg [31:2] VBARb; + + // color lookup table signals + output clut_acc; + input clut_ack; + input [23:0] clut_q; + + + // + // variable declarations + // + parameter REG_ADR_HIBIT = 7; + + wire [REG_ADR_HIBIT:0] REG_ADR = adr_i[REG_ADR_HIBIT : 2]; + wire CLUT_ADR = adr_i[11]; + + parameter [REG_ADR_HIBIT : 0] CTRL_ADR = 6'b00_0000; + parameter [REG_ADR_HIBIT : 0] STAT_ADR = 6'b00_0001; + parameter [REG_ADR_HIBIT : 0] HTIM_ADR = 6'b00_0010; + parameter [REG_ADR_HIBIT : 0] VTIM_ADR = 6'b00_0011; + parameter [REG_ADR_HIBIT : 0] HVLEN_ADR = 6'b00_0100; + parameter [REG_ADR_HIBIT : 0] VBARA_ADR = 6'b00_0101; + parameter [REG_ADR_HIBIT : 0] VBARB_ADR = 6'b00_0110; + parameter [REG_ADR_HIBIT : 0] C0XY_ADR = 6'b00_1100; + parameter [REG_ADR_HIBIT : 0] C0BAR_ADR = 6'b00_1101; + parameter [REG_ADR_HIBIT : 0] CCR0_ADR = 6'b01_0???; + parameter [REG_ADR_HIBIT : 0] C1XY_ADR = 6'b01_1100; + parameter [REG_ADR_HIBIT : 0] C1BAR_ADR = 6'b01_1101; + parameter [REG_ADR_HIBIT : 0] CCR1_ADR = 6'b10_0???; + + + reg [31:0] ctrl, stat, htim, vtim, hvlen; + wire hint, vint, vbsint, cbsint, luint, sint; + wire hie, vie, vbsie, cbsie; + wire acc, acc32, reg_acc, reg_wacc; + wire cc0_acc, cc1_acc; + wire [31:0] ccr0_dat_o, ccr1_dat_o; + + + reg [31:0] reg_dato; // data output from registers + + // + // Module body + // + + assign acc = cyc_i & stb_i; + assign acc32 = (sel_i == 4'b1111); + assign clut_acc = CLUT_ADR & acc & acc32; + assign reg_acc = ~CLUT_ADR & acc & acc32; + assign reg_wacc = reg_acc & we_i; + + assign cc0_acc = (REG_ADR == CCR0_ADR) & acc & acc32; + assign cc1_acc = (REG_ADR == CCR1_ADR) & acc & acc32; + + always @(posedge clk_i) + ack_o <= #1 ((reg_acc & acc32) | clut_ack) & ~(wbm_busy & REG_ADR == CTRL_ADR) & ~ack_o ; + + always @(posedge clk_i) + rty_o <= #1 ((reg_acc & acc32) | clut_ack) & (wbm_busy & REG_ADR == CTRL_ADR) & ~rty_o ; + + always @(posedge clk_i) + err_o <= #1 acc & ~acc32 & ~err_o; + + + // generate registers + always @(posedge clk_i or negedge arst_i) + begin : gen_regs + if (!arst_i) + begin + htim <= #1 0; + vtim <= #1 0; + hvlen <= #1 0; + VBARa <= #1 0; + VBARb <= #1 0; + cursor0_xy <= #1 0; + cursor0_ba <= #1 0; + cursor1_xy <= #1 0; + cursor1_ba <= #1 0; + end + else if (rst_i) + begin + htim <= #1 0; + vtim <= #1 0; + hvlen <= #1 0; + VBARa <= #1 0; + VBARb <= #1 0; + cursor0_xy <= #1 0; + cursor0_ba <= #1 0; + cursor1_xy <= #1 0; + cursor1_ba <= #1 0; + end + else if (reg_wacc) + case (adr_i) // synopsis full_case parallel_case + HTIM_ADR : htim <= #1 dat_i; + VTIM_ADR : vtim <= #1 dat_i; + HVLEN_ADR : hvlen <= #1 dat_i; + VBARA_ADR : VBARa <= #1 dat_i[31: 2]; + VBARB_ADR : VBARb <= #1 dat_i[31: 2]; + C0XY_ADR : cursor0_xy <= #1 dat_i[31: 0]; + C0BAR_ADR : cursor0_ba <= #1 dat_i[31:11]; + C1XY_ADR : cursor1_xy <= #1 dat_i[31: 0]; + C1BAR_ADR : cursor1_ba <= #1 dat_i[31:11]; + endcase + end + + always @(posedge clk_i) + begin + cursor0_ld <= #1 reg_wacc && (adr_i == C0BAR_ADR); + cursor1_ld <= #1 reg_wacc && (adr_i == C1BAR_ADR); + end + + // generate control register + always @(posedge clk_i or negedge arst_i) + if (!arst_i) + ctrl <= #1 0; + else if (rst_i) + ctrl <= #1 0; + else if (reg_wacc & (REG_ADR == CTRL_ADR) & ~wbm_busy ) + ctrl <= #1 dat_i; + else begin + ctrl[6] <= #1 ctrl[6] & !cbsint_in; + ctrl[5] <= #1 ctrl[5] & !vbsint_in; + end + + + // generate status register + always @(posedge clk_i or negedge arst_i) + if (!arst_i) + stat <= #1 0; + else if (rst_i) + stat <= #1 0; + else begin + `ifdef VGA_HWC1 + stat[21] <= #1 1'b1; + `else + stat[21] <= #1 1'b0; + `endif + `ifdef VGA_HWC0 + stat[20] <= #1 1'b1; + `else + stat[20] <= #1 1'b0; + `endif + + stat[17] <= #1 acmp; + stat[16] <= #1 avmp; + + if (reg_wacc & (REG_ADR == STAT_ADR) ) + begin + stat[7] <= #1 cbsint_in | (stat[7] & !dat_i[7]); + stat[6] <= #1 vbsint_in | (stat[6] & !dat_i[6]); + stat[5] <= #1 hint_in | (stat[5] & !dat_i[5]); + stat[4] <= #1 vint_in | (stat[4] & !dat_i[4]); + stat[1] <= #1 luint_in | (stat[3] & !dat_i[1]); + stat[0] <= #1 sint_in | (stat[0] & !dat_i[0]); + end + else + begin + stat[7] <= #1 stat[7] | cbsint_in; + stat[6] <= #1 stat[6] | vbsint_in; + stat[5] <= #1 stat[5] | hint_in; + stat[4] <= #1 stat[4] | vint_in; + stat[1] <= #1 stat[1] | luint_in; + stat[0] <= #1 stat[0] | sint_in; + end + end + + + // decode control register + assign dvi_odf = ctrl[29:28]; + assign cursor1_res = ctrl[25]; + assign cursor1_en = ctrl[24]; + assign cursor0_res = ctrl[23]; + assign cursor0_en = ctrl[20]; + assign bl = ctrl[15]; + assign csl = ctrl[14]; + assign vsl = ctrl[13]; + assign hsl = ctrl[12]; + assign pc = ctrl[11]; + assign cd = ctrl[10:9]; + assign vbl = ctrl[8:7]; + assign cbsw = ctrl[6]; + assign vbsw = ctrl[5]; + assign cbsie = ctrl[4]; + assign vbsie = ctrl[3]; + assign hie = ctrl[2]; + assign vie = ctrl[1]; + assign ven = ctrl[0]; + + // decode status register + assign cbsint = stat[7]; + assign vbsint = stat[6]; + assign hint = stat[5]; + assign vint = stat[4]; + assign luint = stat[1]; + assign sint = stat[0]; + + // decode Horizontal Timing Register + assign Thsync = htim[31:24]; + assign Thgdel = htim[23:16]; + assign Thgate = htim[15:0]; + assign Thlen = hvlen[31:16]; + + // decode Vertical Timing Register + assign Tvsync = vtim[31:24]; + assign Tvgdel = vtim[23:16]; + assign Tvgate = vtim[15:0]; + assign Tvlen = hvlen[15:0]; + + + `ifdef VGA_HWC0 + // hookup cursor0 color registers + vga_cur_cregs cregs0( + .clk_i(clk_i), + .rst_i(rst_i), + .arst_i(arst_i), + .hsel_i(cc0_acc), + .hadr_i(adr_i[4:2]), + .hwe_i(we_i), + .hdat_i(dat_i), + .hdat_o(ccr0_dat_o), // host access + .hack_o(), + .cadr_i(cc0_adr_i), + .cdat_o(cc0_dat_o) // cursor processor access + ); + `else + assign ccr0_dat_o = 32'h0; + assign cc0_dat_o = 32'h0; + `endif + + `ifdef VGA_HWC1 + // hookup cursor1 color registers + vga_cur_cregs cregs1( + .clk_i(clk_i), + .rst_i(rst_i), + .arst_i(arst_i), + .hsel_i(cc1_acc), + .hadr_i(adr_i[4:2]), + .hwe_i(we_i), + .hdat_i(dat_i), + .hdat_o(ccr1_dat_o), // host access + .hack_o(), + .cadr_i(cc1_adr_i), + .cdat_o(cc1_dat_o) // cursor processor access + ); + `else + assign ccr1_dat_o = 32'h0; + assign cc1_dat_o = 32'h0; + `endif + + + // assign output + always @(REG_ADR or ctrl or stat or htim or vtim or hvlen or VBARa or VBARb or acmp or + cursor0_xy or cursor0_ba or cursor1_xy or cursor1_ba or ccr0_dat_o or ccr1_dat_o) + casez (REG_ADR) // synopsis full_case parallel_case + CTRL_ADR : reg_dato = ctrl; + STAT_ADR : reg_dato = stat; + HTIM_ADR : reg_dato = htim; + VTIM_ADR : reg_dato = vtim; + HVLEN_ADR : reg_dato = hvlen; + VBARA_ADR : reg_dato = {VBARa, 2'b0}; + VBARB_ADR : reg_dato = {VBARb, 2'b0}; + C0XY_ADR : reg_dato = cursor0_xy; + C0BAR_ADR : reg_dato = {cursor0_ba, 11'h0}; + CCR0_ADR : reg_dato = ccr0_dat_o; + C1XY_ADR : reg_dato = cursor1_xy; + C1BAR_ADR : reg_dato = {cursor1_ba, 11'h0}; + CCR1_ADR : reg_dato = ccr1_dat_o; + default : reg_dato = 32'h0000_0000; + endcase + + always @(posedge clk_i) + dat_o <= #1 reg_acc ? reg_dato : {8'h0, clut_q}; + + // generate interrupt request signal + always @(posedge clk_i) + inta_o <= #1 (hint & hie) | (vint & vie) | (vbsint & vbsie) | (cbsint & cbsie) | luint | sint; +endmodule + + + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v new file mode 100644 index 000000000..4a50e873e --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v @@ -0,0 +1,267 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// General Round Robin Arbiter //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_arb.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_arb.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:40 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_arb(clk, rst, req, gnt, next); + +input clk; +input rst; +input [7:0] req; // Req input +output [2:0] gnt; // Grant output +input next; // Next Target + +/////////////////////////////////////////////////////////////////////// +// +// Parameters +// + +parameter [2:0] + grant0 = 3'h0, + grant1 = 3'h1, + grant2 = 3'h2, + grant3 = 3'h3, + grant4 = 3'h4, + grant5 = 3'h5, + grant6 = 3'h6, + grant7 = 3'h7; + +/////////////////////////////////////////////////////////////////////// +// +// Local Registers and Wires +// + +reg [2:0] state, next_state; + +/////////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign gnt = state; + +always@(posedge clk or posedge rst) + if(rst) state <= #1 grant0; + else state <= #1 next_state; + +/////////////////////////////////////////////////////////////////////// +// +// Next State Logic +// - implements round robin arbitration algorithm +// - switches grant if current req is dropped or next is asserted +// - parks at last grant +// + +always@(state or req or next) + begin + next_state = state; // Default Keep State + case(state) // synopsys parallel_case full_case + grant0: + // if this req is dropped or next is asserted, check for other req's + if(!req[0] | next) + begin + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + end + grant1: + // if this req is dropped or next is asserted, check for other req's + if(!req[1] | next) + begin + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + end + grant2: + // if this req is dropped or next is asserted, check for other req's + if(!req[2] | next) + begin + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + end + grant3: + // if this req is dropped or next is asserted, check for other req's + if(!req[3] | next) + begin + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + end + grant4: + // if this req is dropped or next is asserted, check for other req's + if(!req[4] | next) + begin + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + end + grant5: + // if this req is dropped or next is asserted, check for other req's + if(!req[5] | next) + begin + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + end + grant6: + // if this req is dropped or next is asserted, check for other req's + if(!req[6] | next) + begin + if(req[7]) next_state = grant7; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + end + grant7: + // if this req is dropped or next is asserted, check for other req's + if(!req[7] | next) + begin + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + end + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v new file mode 100644 index 000000000..1f0968505 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Definitions //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_defines.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_defines.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:40 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// +// +// + +`timescale 1ns / 10ps + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v new file mode 100644 index 000000000..51fc868d0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v @@ -0,0 +1,659 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Master Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_master_if.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_master_if.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:41 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_master_if( + + clk_i, rst_i, + + // Master interface + wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, wb_rty_o, + + // Slave 0 Interface + s0_data_i, s0_data_o, s0_addr_o, s0_sel_o, s0_we_o, s0_cyc_o, + s0_stb_o, s0_ack_i, s0_err_i, s0_rty_i, + + // Slave 1 Interface + s1_data_i, s1_data_o, s1_addr_o, s1_sel_o, s1_we_o, s1_cyc_o, + s1_stb_o, s1_ack_i, s1_err_i, s1_rty_i, + + // Slave 2 Interface + s2_data_i, s2_data_o, s2_addr_o, s2_sel_o, s2_we_o, s2_cyc_o, + s2_stb_o, s2_ack_i, s2_err_i, s2_rty_i, + + // Slave 3 Interface + s3_data_i, s3_data_o, s3_addr_o, s3_sel_o, s3_we_o, s3_cyc_o, + s3_stb_o, s3_ack_i, s3_err_i, s3_rty_i, + + // Slave 4 Interface + s4_data_i, s4_data_o, s4_addr_o, s4_sel_o, s4_we_o, s4_cyc_o, + s4_stb_o, s4_ack_i, s4_err_i, s4_rty_i, + + // Slave 5 Interface + s5_data_i, s5_data_o, s5_addr_o, s5_sel_o, s5_we_o, s5_cyc_o, + s5_stb_o, s5_ack_i, s5_err_i, s5_rty_i, + + // Slave 6 Interface + s6_data_i, s6_data_o, s6_addr_o, s6_sel_o, s6_we_o, s6_cyc_o, + s6_stb_o, s6_ack_i, s6_err_i, s6_rty_i, + + // Slave 7 Interface + s7_data_i, s7_data_o, s7_addr_o, s7_sel_o, s7_we_o, s7_cyc_o, + s7_stb_o, s7_ack_i, s7_err_i, s7_rty_i, + + // Slave 8 Interface + s8_data_i, s8_data_o, s8_addr_o, s8_sel_o, s8_we_o, s8_cyc_o, + s8_stb_o, s8_ack_i, s8_err_i, s8_rty_i, + + // Slave 9 Interface + s9_data_i, s9_data_o, s9_addr_o, s9_sel_o, s9_we_o, s9_cyc_o, + s9_stb_o, s9_ack_i, s9_err_i, s9_rty_i, + + // Slave 10 Interface + s10_data_i, s10_data_o, s10_addr_o, s10_sel_o, s10_we_o, s10_cyc_o, + s10_stb_o, s10_ack_i, s10_err_i, s10_rty_i, + + // Slave 11 Interface + s11_data_i, s11_data_o, s11_addr_o, s11_sel_o, s11_we_o, s11_cyc_o, + s11_stb_o, s11_ack_i, s11_err_i, s11_rty_i, + + // Slave 12 Interface + s12_data_i, s12_data_o, s12_addr_o, s12_sel_o, s12_we_o, s12_cyc_o, + s12_stb_o, s12_ack_i, s12_err_i, s12_rty_i, + + // Slave 13 Interface + s13_data_i, s13_data_o, s13_addr_o, s13_sel_o, s13_we_o, s13_cyc_o, + s13_stb_o, s13_ack_i, s13_err_i, s13_rty_i, + + // Slave 14 Interface + s14_data_i, s14_data_o, s14_addr_o, s14_sel_o, s14_we_o, s14_cyc_o, + s14_stb_o, s14_ack_i, s14_err_i, s14_rty_i, + + // Slave 15 Interface + s15_data_i, s15_data_o, s15_addr_o, s15_sel_o, s15_we_o, s15_cyc_o, + s15_stb_o, s15_ack_i, s15_err_i, s15_rty_i + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter dw = 32; // Data bus Width +parameter aw = 32; // Address bus Width +parameter sw = dw / 8; // Number of Select Lines + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; + +// Master Interface +input [dw-1:0] wb_data_i; +output [dw-1:0] wb_data_o; +input [aw-1:0] wb_addr_i; +input [sw-1:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; +output wb_rty_o; + +// Slave 0 Interface +input [dw-1:0] s0_data_i; +output [dw-1:0] s0_data_o; +output [aw-1:0] s0_addr_o; +output [sw-1:0] s0_sel_o; +output s0_we_o; +output s0_cyc_o; +output s0_stb_o; +input s0_ack_i; +input s0_err_i; +input s0_rty_i; + +// Slave 1 Interface +input [dw-1:0] s1_data_i; +output [dw-1:0] s1_data_o; +output [aw-1:0] s1_addr_o; +output [sw-1:0] s1_sel_o; +output s1_we_o; +output s1_cyc_o; +output s1_stb_o; +input s1_ack_i; +input s1_err_i; +input s1_rty_i; + +// Slave 2 Interface +input [dw-1:0] s2_data_i; +output [dw-1:0] s2_data_o; +output [aw-1:0] s2_addr_o; +output [sw-1:0] s2_sel_o; +output s2_we_o; +output s2_cyc_o; +output s2_stb_o; +input s2_ack_i; +input s2_err_i; +input s2_rty_i; + +// Slave 3 Interface +input [dw-1:0] s3_data_i; +output [dw-1:0] s3_data_o; +output [aw-1:0] s3_addr_o; +output [sw-1:0] s3_sel_o; +output s3_we_o; +output s3_cyc_o; +output s3_stb_o; +input s3_ack_i; +input s3_err_i; +input s3_rty_i; + +// Slave 4 Interface +input [dw-1:0] s4_data_i; +output [dw-1:0] s4_data_o; +output [aw-1:0] s4_addr_o; +output [sw-1:0] s4_sel_o; +output s4_we_o; +output s4_cyc_o; +output s4_stb_o; +input s4_ack_i; +input s4_err_i; +input s4_rty_i; + +// Slave 5 Interface +input [dw-1:0] s5_data_i; +output [dw-1:0] s5_data_o; +output [aw-1:0] s5_addr_o; +output [sw-1:0] s5_sel_o; +output s5_we_o; +output s5_cyc_o; +output s5_stb_o; +input s5_ack_i; +input s5_err_i; +input s5_rty_i; + +// Slave 6 Interface +input [dw-1:0] s6_data_i; +output [dw-1:0] s6_data_o; +output [aw-1:0] s6_addr_o; +output [sw-1:0] s6_sel_o; +output s6_we_o; +output s6_cyc_o; +output s6_stb_o; +input s6_ack_i; +input s6_err_i; +input s6_rty_i; + +// Slave 7 Interface +input [dw-1:0] s7_data_i; +output [dw-1:0] s7_data_o; +output [aw-1:0] s7_addr_o; +output [sw-1:0] s7_sel_o; +output s7_we_o; +output s7_cyc_o; +output s7_stb_o; +input s7_ack_i; +input s7_err_i; +input s7_rty_i; + +// Slave 8 Interface +input [dw-1:0] s8_data_i; +output [dw-1:0] s8_data_o; +output [aw-1:0] s8_addr_o; +output [sw-1:0] s8_sel_o; +output s8_we_o; +output s8_cyc_o; +output s8_stb_o; +input s8_ack_i; +input s8_err_i; +input s8_rty_i; + +// Slave 9 Interface +input [dw-1:0] s9_data_i; +output [dw-1:0] s9_data_o; +output [aw-1:0] s9_addr_o; +output [sw-1:0] s9_sel_o; +output s9_we_o; +output s9_cyc_o; +output s9_stb_o; +input s9_ack_i; +input s9_err_i; +input s9_rty_i; + +// Slave 10 Interface +input [dw-1:0] s10_data_i; +output [dw-1:0] s10_data_o; +output [aw-1:0] s10_addr_o; +output [sw-1:0] s10_sel_o; +output s10_we_o; +output s10_cyc_o; +output s10_stb_o; +input s10_ack_i; +input s10_err_i; +input s10_rty_i; + +// Slave 11 Interface +input [dw-1:0] s11_data_i; +output [dw-1:0] s11_data_o; +output [aw-1:0] s11_addr_o; +output [sw-1:0] s11_sel_o; +output s11_we_o; +output s11_cyc_o; +output s11_stb_o; +input s11_ack_i; +input s11_err_i; +input s11_rty_i; + +// Slave 12 Interface +input [dw-1:0] s12_data_i; +output [dw-1:0] s12_data_o; +output [aw-1:0] s12_addr_o; +output [sw-1:0] s12_sel_o; +output s12_we_o; +output s12_cyc_o; +output s12_stb_o; +input s12_ack_i; +input s12_err_i; +input s12_rty_i; + +// Slave 13 Interface +input [dw-1:0] s13_data_i; +output [dw-1:0] s13_data_o; +output [aw-1:0] s13_addr_o; +output [sw-1:0] s13_sel_o; +output s13_we_o; +output s13_cyc_o; +output s13_stb_o; +input s13_ack_i; +input s13_err_i; +input s13_rty_i; + +// Slave 14 Interface +input [dw-1:0] s14_data_i; +output [dw-1:0] s14_data_o; +output [aw-1:0] s14_addr_o; +output [sw-1:0] s14_sel_o; +output s14_we_o; +output s14_cyc_o; +output s14_stb_o; +input s14_ack_i; +input s14_err_i; +input s14_rty_i; + +// Slave 15 Interface +input [dw-1:0] s15_data_i; +output [dw-1:0] s15_data_o; +output [aw-1:0] s15_addr_o; +output [sw-1:0] s15_sel_o; +output s15_we_o; +output s15_cyc_o; +output s15_stb_o; +input s15_ack_i; +input s15_err_i; +input s15_rty_i; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [dw-1:0] wb_data_o; +reg wb_ack_o; +reg wb_err_o; +reg wb_rty_o; +wire [3:0] slv_sel; + +wire s0_cyc_o_next, s1_cyc_o_next, s2_cyc_o_next, s3_cyc_o_next; +wire s4_cyc_o_next, s5_cyc_o_next, s6_cyc_o_next, s7_cyc_o_next; +wire s8_cyc_o_next, s9_cyc_o_next, s10_cyc_o_next, s11_cyc_o_next; +wire s12_cyc_o_next, s13_cyc_o_next, s14_cyc_o_next, s15_cyc_o_next; + +reg s0_cyc_o, s1_cyc_o, s2_cyc_o, s3_cyc_o; +reg s4_cyc_o, s5_cyc_o, s6_cyc_o, s7_cyc_o; +reg s8_cyc_o, s9_cyc_o, s10_cyc_o, s11_cyc_o; +reg s12_cyc_o, s13_cyc_o, s14_cyc_o, s15_cyc_o; + +//////////////////////////////////////////////////////////////////// +// +// Select logic +// + +assign slv_sel = wb_addr_i[aw-1:aw-4]; + +//////////////////////////////////////////////////////////////////// +// +// Address & Data Pass +// + +assign s0_addr_o = wb_addr_i; +assign s1_addr_o = wb_addr_i; +assign s2_addr_o = wb_addr_i; +assign s3_addr_o = wb_addr_i; +assign s4_addr_o = wb_addr_i; +assign s5_addr_o = wb_addr_i; +assign s6_addr_o = wb_addr_i; +assign s7_addr_o = wb_addr_i; +assign s8_addr_o = wb_addr_i; +assign s9_addr_o = wb_addr_i; +assign s10_addr_o = wb_addr_i; +assign s11_addr_o = wb_addr_i; +assign s12_addr_o = wb_addr_i; +assign s13_addr_o = wb_addr_i; +assign s14_addr_o = wb_addr_i; +assign s15_addr_o = wb_addr_i; + +assign s0_sel_o = wb_sel_i; +assign s1_sel_o = wb_sel_i; +assign s2_sel_o = wb_sel_i; +assign s3_sel_o = wb_sel_i; +assign s4_sel_o = wb_sel_i; +assign s5_sel_o = wb_sel_i; +assign s6_sel_o = wb_sel_i; +assign s7_sel_o = wb_sel_i; +assign s8_sel_o = wb_sel_i; +assign s9_sel_o = wb_sel_i; +assign s10_sel_o = wb_sel_i; +assign s11_sel_o = wb_sel_i; +assign s12_sel_o = wb_sel_i; +assign s13_sel_o = wb_sel_i; +assign s14_sel_o = wb_sel_i; +assign s15_sel_o = wb_sel_i; + +assign s0_data_o = wb_data_i; +assign s1_data_o = wb_data_i; +assign s2_data_o = wb_data_i; +assign s3_data_o = wb_data_i; +assign s4_data_o = wb_data_i; +assign s5_data_o = wb_data_i; +assign s6_data_o = wb_data_i; +assign s7_data_o = wb_data_i; +assign s8_data_o = wb_data_i; +assign s9_data_o = wb_data_i; +assign s10_data_o = wb_data_i; +assign s11_data_o = wb_data_i; +assign s12_data_o = wb_data_i; +assign s13_data_o = wb_data_i; +assign s14_data_o = wb_data_i; +assign s15_data_o = wb_data_i; + +always @(slv_sel or s0_data_i or s1_data_i or s2_data_i or s3_data_i or + s4_data_i or s5_data_i or s6_data_i or s7_data_i or s8_data_i or + s9_data_i or s10_data_i or s11_data_i or s12_data_i or + s13_data_i or s14_data_i or s15_data_i) + case(slv_sel) // synopsys parallel_case + 4'd0: wb_data_o = s0_data_i; + 4'd1: wb_data_o = s1_data_i; + 4'd2: wb_data_o = s2_data_i; + 4'd3: wb_data_o = s3_data_i; + 4'd4: wb_data_o = s4_data_i; + 4'd5: wb_data_o = s5_data_i; + 4'd6: wb_data_o = s6_data_i; + 4'd7: wb_data_o = s7_data_i; + 4'd8: wb_data_o = s8_data_i; + 4'd9: wb_data_o = s9_data_i; + 4'd10: wb_data_o = s10_data_i; + 4'd11: wb_data_o = s11_data_i; + 4'd12: wb_data_o = s12_data_i; + 4'd13: wb_data_o = s13_data_i; + 4'd14: wb_data_o = s14_data_i; + 4'd15: wb_data_o = s15_data_i; + default: wb_data_o = {dw{1'bx}}; + endcase + +//////////////////////////////////////////////////////////////////// +// +// Control Signal Pass +// + +assign s0_we_o = wb_we_i; +assign s1_we_o = wb_we_i; +assign s2_we_o = wb_we_i; +assign s3_we_o = wb_we_i; +assign s4_we_o = wb_we_i; +assign s5_we_o = wb_we_i; +assign s6_we_o = wb_we_i; +assign s7_we_o = wb_we_i; +assign s8_we_o = wb_we_i; +assign s9_we_o = wb_we_i; +assign s10_we_o = wb_we_i; +assign s11_we_o = wb_we_i; +assign s12_we_o = wb_we_i; +assign s13_we_o = wb_we_i; +assign s14_we_o = wb_we_i; +assign s15_we_o = wb_we_i; + +assign s0_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s0_cyc_o : ((slv_sel==4'd0) ? wb_cyc_i : 1'b0); +assign s1_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s1_cyc_o : ((slv_sel==4'd1) ? wb_cyc_i : 1'b0); +assign s2_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s2_cyc_o : ((slv_sel==4'd2) ? wb_cyc_i : 1'b0); +assign s3_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s3_cyc_o : ((slv_sel==4'd3) ? wb_cyc_i : 1'b0); +assign s4_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s4_cyc_o : ((slv_sel==4'd4) ? wb_cyc_i : 1'b0); +assign s5_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s5_cyc_o : ((slv_sel==4'd5) ? wb_cyc_i : 1'b0); +assign s6_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s6_cyc_o : ((slv_sel==4'd6) ? wb_cyc_i : 1'b0); +assign s7_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s7_cyc_o : ((slv_sel==4'd7) ? wb_cyc_i : 1'b0); +assign s8_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s8_cyc_o : ((slv_sel==4'd8) ? wb_cyc_i : 1'b0); +assign s9_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s9_cyc_o : ((slv_sel==4'd9) ? wb_cyc_i : 1'b0); +assign s10_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s10_cyc_o : ((slv_sel==4'd10) ? wb_cyc_i : 1'b0); +assign s11_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s11_cyc_o : ((slv_sel==4'd11) ? wb_cyc_i : 1'b0); +assign s12_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s12_cyc_o : ((slv_sel==4'd12) ? wb_cyc_i : 1'b0); +assign s13_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s13_cyc_o : ((slv_sel==4'd13) ? wb_cyc_i : 1'b0); +assign s14_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s14_cyc_o : ((slv_sel==4'd14) ? wb_cyc_i : 1'b0); +assign s15_cyc_o_next = (wb_cyc_i & !wb_stb_i) ? s15_cyc_o : ((slv_sel==4'd15) ? wb_cyc_i : 1'b0); + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s0_cyc_o <= #1 1'b0; + else s0_cyc_o <= #1 s0_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s1_cyc_o <= #1 1'b0; + else s1_cyc_o <= #1 s1_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s2_cyc_o <= #1 1'b0; + else s2_cyc_o <= #1 s2_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s3_cyc_o <= #1 1'b0; + else s3_cyc_o <= #1 s3_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s4_cyc_o <= #1 1'b0; + else s4_cyc_o <= #1 s4_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s5_cyc_o <= #1 1'b0; + else s5_cyc_o <= #1 s5_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s6_cyc_o <= #1 1'b0; + else s6_cyc_o <= #1 s6_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s7_cyc_o <= #1 1'b0; + else s7_cyc_o <= #1 s7_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s8_cyc_o <= #1 1'b0; + else s8_cyc_o <= #1 s8_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s9_cyc_o <= #1 1'b0; + else s9_cyc_o <= #1 s9_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s10_cyc_o <= #1 1'b0; + else s10_cyc_o <= #1 s10_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s11_cyc_o <= #1 1'b0; + else s11_cyc_o <= #1 s11_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s12_cyc_o <= #1 1'b0; + else s12_cyc_o <= #1 s12_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s13_cyc_o <= #1 1'b0; + else s13_cyc_o <= #1 s13_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s14_cyc_o <= #1 1'b0; + else s14_cyc_o <= #1 s14_cyc_o_next; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) s15_cyc_o <= #1 1'b0; + else s15_cyc_o <= #1 s15_cyc_o_next; + +assign s0_stb_o = (slv_sel==4'd0) ? wb_stb_i : 1'b0; +assign s1_stb_o = (slv_sel==4'd1) ? wb_stb_i : 1'b0; +assign s2_stb_o = (slv_sel==4'd2) ? wb_stb_i : 1'b0; +assign s3_stb_o = (slv_sel==4'd3) ? wb_stb_i : 1'b0; +assign s4_stb_o = (slv_sel==4'd4) ? wb_stb_i : 1'b0; +assign s5_stb_o = (slv_sel==4'd5) ? wb_stb_i : 1'b0; +assign s6_stb_o = (slv_sel==4'd6) ? wb_stb_i : 1'b0; +assign s7_stb_o = (slv_sel==4'd7) ? wb_stb_i : 1'b0; +assign s8_stb_o = (slv_sel==4'd8) ? wb_stb_i : 1'b0; +assign s9_stb_o = (slv_sel==4'd9) ? wb_stb_i : 1'b0; +assign s10_stb_o = (slv_sel==4'd10) ? wb_stb_i : 1'b0; +assign s11_stb_o = (slv_sel==4'd11) ? wb_stb_i : 1'b0; +assign s12_stb_o = (slv_sel==4'd12) ? wb_stb_i : 1'b0; +assign s13_stb_o = (slv_sel==4'd13) ? wb_stb_i : 1'b0; +assign s14_stb_o = (slv_sel==4'd14) ? wb_stb_i : 1'b0; +assign s15_stb_o = (slv_sel==4'd15) ? wb_stb_i : 1'b0; + +always @(slv_sel or s0_ack_i or s1_ack_i or s2_ack_i or s3_ack_i or + s4_ack_i or s5_ack_i or s6_ack_i or s7_ack_i or s8_ack_i or + s9_ack_i or s10_ack_i or s11_ack_i or s12_ack_i or + s13_ack_i or s14_ack_i or s15_ack_i) + case(slv_sel) // synopsys parallel_case + 4'd0: wb_ack_o = s0_ack_i; + 4'd1: wb_ack_o = s1_ack_i; + 4'd2: wb_ack_o = s2_ack_i; + 4'd3: wb_ack_o = s3_ack_i; + 4'd4: wb_ack_o = s4_ack_i; + 4'd5: wb_ack_o = s5_ack_i; + 4'd6: wb_ack_o = s6_ack_i; + 4'd7: wb_ack_o = s7_ack_i; + 4'd8: wb_ack_o = s8_ack_i; + 4'd9: wb_ack_o = s9_ack_i; + 4'd10: wb_ack_o = s10_ack_i; + 4'd11: wb_ack_o = s11_ack_i; + 4'd12: wb_ack_o = s12_ack_i; + 4'd13: wb_ack_o = s13_ack_i; + 4'd14: wb_ack_o = s14_ack_i; + 4'd15: wb_ack_o = s15_ack_i; + default: wb_ack_o = 1'b0; + endcase + +always @(slv_sel or s0_err_i or s1_err_i or s2_err_i or s3_err_i or + s4_err_i or s5_err_i or s6_err_i or s7_err_i or s8_err_i or + s9_err_i or s10_err_i or s11_err_i or s12_err_i or + s13_err_i or s14_err_i or s15_err_i) + case(slv_sel) // synopsys parallel_case + 4'd0: wb_err_o = s0_err_i; + 4'd1: wb_err_o = s1_err_i; + 4'd2: wb_err_o = s2_err_i; + 4'd3: wb_err_o = s3_err_i; + 4'd4: wb_err_o = s4_err_i; + 4'd5: wb_err_o = s5_err_i; + 4'd6: wb_err_o = s6_err_i; + 4'd7: wb_err_o = s7_err_i; + 4'd8: wb_err_o = s8_err_i; + 4'd9: wb_err_o = s9_err_i; + 4'd10: wb_err_o = s10_err_i; + 4'd11: wb_err_o = s11_err_i; + 4'd12: wb_err_o = s12_err_i; + 4'd13: wb_err_o = s13_err_i; + 4'd14: wb_err_o = s14_err_i; + 4'd15: wb_err_o = s15_err_i; + default: wb_err_o = 1'b0; + endcase + +always @(slv_sel or s0_rty_i or s1_rty_i or s2_rty_i or s3_rty_i or + s4_rty_i or s5_rty_i or s6_rty_i or s7_rty_i or s8_rty_i or + s9_rty_i or s10_rty_i or s11_rty_i or s12_rty_i or + s13_rty_i or s14_rty_i or s15_rty_i) + case(slv_sel) // synopsys parallel_case + 4'd0: wb_rty_o = s0_rty_i; + 4'd1: wb_rty_o = s1_rty_i; + 4'd2: wb_rty_o = s2_rty_i; + 4'd3: wb_rty_o = s3_rty_i; + 4'd4: wb_rty_o = s4_rty_i; + 4'd5: wb_rty_o = s5_rty_i; + 4'd6: wb_rty_o = s6_rty_i; + 4'd7: wb_rty_o = s7_rty_i; + 4'd8: wb_rty_o = s8_rty_i; + 4'd9: wb_rty_o = s9_rty_i; + 4'd10: wb_rty_o = s10_rty_i; + 4'd11: wb_rty_o = s11_rty_i; + 4'd12: wb_rty_o = s12_rty_i; + 4'd13: wb_rty_o = s13_rty_i; + 4'd14: wb_rty_o = s14_rty_i; + 4'd15: wb_rty_o = s15_rty_i; + default: wb_rty_o = 1'b0; + endcase + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v new file mode 100644 index 000000000..7dd76759d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v @@ -0,0 +1,246 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Master Select //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_msel.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_msel.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:38 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_msel( + clk_i, rst_i, + conf, req, sel, next + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter [1:0] pri_sel = 2'd0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; +input [15:0] conf; +input [7:0] req; +output [2:0] sel; +input next; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [1:0] pri0, pri1, pri2, pri3; +wire [1:0] pri4, pri5, pri6, pri7; +wire [1:0] pri_out_d; +reg [1:0] pri_out; + +wire [7:0] req_p0, req_p1, req_p2, req_p3; +wire [2:0] gnt_p0, gnt_p1, gnt_p2, gnt_p3; + +reg [2:0] sel1, sel2; +wire [2:0] sel; + +//////////////////////////////////////////////////////////////////// +// +// Priority Select logic +// + +assign pri0[0] = (pri_sel == 2'd0) ? 1'b0 : conf[0]; +assign pri0[1] = (pri_sel == 2'd2) ? conf[1] : 1'b0; + +assign pri1[0] = (pri_sel == 2'd0) ? 1'b0 : conf[2]; +assign pri1[1] = (pri_sel == 2'd2) ? conf[3] : 1'b0; + +assign pri2[0] = (pri_sel == 2'd0) ? 1'b0 : conf[4]; +assign pri2[1] = (pri_sel == 2'd2) ? conf[5] : 1'b0; + +assign pri3[0] = (pri_sel == 2'd0) ? 1'b0 : conf[6]; +assign pri3[1] = (pri_sel == 2'd2) ? conf[7] : 1'b0; + +assign pri4[0] = (pri_sel == 2'd0) ? 1'b0 : conf[8]; +assign pri4[1] = (pri_sel == 2'd2) ? conf[9] : 1'b0; + +assign pri5[0] = (pri_sel == 2'd0) ? 1'b0 : conf[10]; +assign pri5[1] = (pri_sel == 2'd2) ? conf[11] : 1'b0; + +assign pri6[0] = (pri_sel == 2'd0) ? 1'b0 : conf[12]; +assign pri6[1] = (pri_sel == 2'd2) ? conf[13] : 1'b0; + +assign pri7[0] = (pri_sel == 2'd0) ? 1'b0 : conf[14]; +assign pri7[1] = (pri_sel == 2'd2) ? conf[15] : 1'b0; + +// Priority Encoder +wb_conmax_pri_enc #(pri_sel) pri_enc( + .valid( req ), + .pri0( pri0 ), + .pri1( pri1 ), + .pri2( pri2 ), + .pri3( pri3 ), + .pri4( pri4 ), + .pri5( pri5 ), + .pri6( pri6 ), + .pri7( pri7 ), + .pri_out( pri_out_d ) + ); + +always @(posedge clk_i) + if(rst_i) pri_out <= #1 2'h0; + else + if(next) pri_out <= #1 pri_out_d; + +//////////////////////////////////////////////////////////////////// +// +// Arbiters +// + +assign req_p0[0] = req[0] & (pri0 == 2'd0); +assign req_p0[1] = req[1] & (pri1 == 2'd0); +assign req_p0[2] = req[2] & (pri2 == 2'd0); +assign req_p0[3] = req[3] & (pri3 == 2'd0); +assign req_p0[4] = req[4] & (pri4 == 2'd0); +assign req_p0[5] = req[5] & (pri5 == 2'd0); +assign req_p0[6] = req[6] & (pri6 == 2'd0); +assign req_p0[7] = req[7] & (pri7 == 2'd0); + +assign req_p1[0] = req[0] & (pri0 == 2'd1); +assign req_p1[1] = req[1] & (pri1 == 2'd1); +assign req_p1[2] = req[2] & (pri2 == 2'd1); +assign req_p1[3] = req[3] & (pri3 == 2'd1); +assign req_p1[4] = req[4] & (pri4 == 2'd1); +assign req_p1[5] = req[5] & (pri5 == 2'd1); +assign req_p1[6] = req[6] & (pri6 == 2'd1); +assign req_p1[7] = req[7] & (pri7 == 2'd1); + +assign req_p2[0] = req[0] & (pri0 == 2'd2); +assign req_p2[1] = req[1] & (pri1 == 2'd2); +assign req_p2[2] = req[2] & (pri2 == 2'd2); +assign req_p2[3] = req[3] & (pri3 == 2'd2); +assign req_p2[4] = req[4] & (pri4 == 2'd2); +assign req_p2[5] = req[5] & (pri5 == 2'd2); +assign req_p2[6] = req[6] & (pri6 == 2'd2); +assign req_p2[7] = req[7] & (pri7 == 2'd2); + +assign req_p3[0] = req[0] & (pri0 == 2'd3); +assign req_p3[1] = req[1] & (pri1 == 2'd3); +assign req_p3[2] = req[2] & (pri2 == 2'd3); +assign req_p3[3] = req[3] & (pri3 == 2'd3); +assign req_p3[4] = req[4] & (pri4 == 2'd3); +assign req_p3[5] = req[5] & (pri5 == 2'd3); +assign req_p3[6] = req[6] & (pri6 == 2'd3); +assign req_p3[7] = req[7] & (pri7 == 2'd3); + +wb_conmax_arb arb0( + .clk( clk_i ), + .rst( rst_i ), + .req( req_p0 ), + .gnt( gnt_p0 ), + .next( 1'b0 ) + ); + +wb_conmax_arb arb1( + .clk( clk_i ), + .rst( rst_i ), + .req( req_p1 ), + .gnt( gnt_p1 ), + .next( 1'b0 ) + ); + +wb_conmax_arb arb2( + .clk( clk_i ), + .rst( rst_i ), + .req( req_p2 ), + .gnt( gnt_p2 ), + .next( 1'b0 ) + ); + +wb_conmax_arb arb3( + .clk( clk_i ), + .rst( rst_i ), + .req( req_p3 ), + .gnt( gnt_p3 ), + .next( 1'b0 ) + ); + +//////////////////////////////////////////////////////////////////// +// +// Final Master Select +// + +always @(pri_out or gnt_p0 or gnt_p1) + if(pri_out[0]) sel1 = gnt_p1; + else sel1 = gnt_p0; + + +always @(pri_out or gnt_p0 or gnt_p1 or gnt_p2 or gnt_p3) + case(pri_out) + 2'd0: sel2 = gnt_p0; + 2'd1: sel2 = gnt_p1; + 2'd2: sel2 = gnt_p2; + 2'd3: sel2 = gnt_p3; + endcase + + +assign sel = (pri_sel==2'd0) ? gnt_p0 : ( (pri_sel==2'd1) ? sel1 : sel2 ); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v new file mode 100644 index 000000000..585c28077 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Priority Decoder //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_pri_dec.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_pri_dec.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:42 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_pri_dec(valid, pri_in, pri_out); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter [1:0] pri_sel = 2'd0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input valid; +input [1:0] pri_in; +output [3:0] pri_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [3:0] pri_out; +reg [3:0] pri_out_d0; +reg [3:0] pri_out_d1; + +//////////////////////////////////////////////////////////////////// +// +// Priority Decoder +// + +// 4 Priority Levels +always @(valid or pri_in) + if(!valid) pri_out_d1 = 4'b0001; + else + if(pri_in==2'h0) pri_out_d1 = 4'b0001; + else + if(pri_in==2'h1) pri_out_d1 = 4'b0010; + else + if(pri_in==2'h2) pri_out_d1 = 4'b0100; + else pri_out_d1 = 4'b1000; + +// 2 Priority Levels +always @(valid or pri_in) + if(!valid) pri_out_d0 = 4'b0001; + else + if(pri_in==2'h0) pri_out_d0 = 4'b0001; + else pri_out_d0 = 4'b0010; + +// Select Configured Priority + +assign pri_out = (pri_sel==2'd0) ? 4'h0 : ( (pri_sel==1'd1) ? pri_out_d0 : pri_out_d1 ); + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v new file mode 100644 index 000000000..6b688f6b6 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v @@ -0,0 +1,186 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Priority Encoder //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_pri_enc.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_pri_enc.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:41 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_pri_enc( + valid, + pri0, pri1, pri2, pri3, + pri4, pri5, pri6, pri7, + pri_out + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter [1:0] pri_sel = 2'd0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input [7:0] valid; +input [1:0] pri0, pri1, pri2, pri3; +input [1:0] pri4, pri5, pri6, pri7; +output [1:0] pri_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [3:0] pri0_out, pri1_out, pri2_out, pri3_out; +wire [3:0] pri4_out, pri5_out, pri6_out, pri7_out; +wire [3:0] pri_out_tmp; +reg [1:0] pri_out0, pri_out1; +wire [1:0] pri_out; + +//////////////////////////////////////////////////////////////////// +// +// Priority Decoders +// + +wb_conmax_pri_dec #(pri_sel) pd0( + .valid( valid[0] ), + .pri_in( pri0 ), + .pri_out( pri0_out ) + ); + + +wb_conmax_pri_dec #(pri_sel) pd1( + .valid( valid[1] ), + .pri_in( pri1 ), + .pri_out( pri1_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd2( + .valid( valid[2] ), + .pri_in( pri2 ), + .pri_out( pri2_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd3( + .valid( valid[3] ), + .pri_in( pri3 ), + .pri_out( pri3_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd4( + .valid( valid[4] ), + .pri_in( pri4 ), + .pri_out( pri4_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd5( + .valid( valid[5] ), + .pri_in( pri5 ), + .pri_out( pri5_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd6( + .valid( valid[6] ), + .pri_in( pri6 ), + .pri_out( pri6_out ) + ); + +wb_conmax_pri_dec #(pri_sel) pd7( + .valid( valid[7] ), + .pri_in( pri7 ), + .pri_out( pri7_out ) + ); + +//////////////////////////////////////////////////////////////////// +// +// Priority Encoding +// + +assign pri_out_tmp = pri0_out | pri1_out | pri2_out | pri3_out | + pri4_out | pri5_out | pri6_out | pri7_out; + +// 4 Priority Levels +always @(pri_out_tmp) + if(pri_out_tmp[3]) pri_out1 = 2'h3; + else + if(pri_out_tmp[2]) pri_out1 = 2'h2; + else + if(pri_out_tmp[1]) pri_out1 = 2'h1; + else pri_out1 = 2'h0; + +// 2 Priority Levels +always @(pri_out_tmp) + if(pri_out_tmp[1]) pri_out0 = 2'h1; + else pri_out0 = 2'h0; + +//////////////////////////////////////////////////////////////////// +// +// Final Priority Output +// + +// Select configured priority + +assign pri_out = (pri_sel==2'd0) ? 2'h0 : ( (pri_sel==2'd1) ? pri_out0 : pri_out1 ); + +endmodule + + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v new file mode 100644 index 000000000..4d76d9075 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v @@ -0,0 +1,311 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_rf.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_rf.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:42 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_rf( + clk_i, rst_i, + + // Internal Wishbone Interface + i_wb_data_i, i_wb_data_o, i_wb_addr_i, i_wb_sel_i, i_wb_we_i, i_wb_cyc_i, + i_wb_stb_i, i_wb_ack_o, i_wb_err_o, i_wb_rty_o, + + // External Wishbone Interface + e_wb_data_i, e_wb_data_o, e_wb_addr_o, e_wb_sel_o, e_wb_we_o, e_wb_cyc_o, + e_wb_stb_o, e_wb_ack_i, e_wb_err_i, e_wb_rty_i, + + // Configuration Registers + conf0, conf1, conf2, conf3, conf4, conf5, conf6, conf7, + conf8, conf9, conf10, conf11, conf12, conf13, conf14, conf15 + + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter [3:0] rf_addr = 4'hf; +parameter dw = 32; // Data bus Width +parameter aw = 32; // Address bus Width +parameter sw = dw / 8; // Number of Select Lines + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; + +// Internal Wishbone Interface +input [dw-1:0] i_wb_data_i; +output [dw-1:0] i_wb_data_o; +input [aw-1:0] i_wb_addr_i; +input [sw-1:0] i_wb_sel_i; +input i_wb_we_i; +input i_wb_cyc_i; +input i_wb_stb_i; +output i_wb_ack_o; +output i_wb_err_o; +output i_wb_rty_o; + +// External Wishbone Interface +input [dw-1:0] e_wb_data_i; +output [dw-1:0] e_wb_data_o; +output [aw-1:0] e_wb_addr_o; +output [sw-1:0] e_wb_sel_o; +output e_wb_we_o; +output e_wb_cyc_o; +output e_wb_stb_o; +input e_wb_ack_i; +input e_wb_err_i; +input e_wb_rty_i; + +// Configuration Registers +output [15:0] conf0; +output [15:0] conf1; +output [15:0] conf2; +output [15:0] conf3; +output [15:0] conf4; +output [15:0] conf5; +output [15:0] conf6; +output [15:0] conf7; +output [15:0] conf8; +output [15:0] conf9; +output [15:0] conf10; +output [15:0] conf11; +output [15:0] conf12; +output [15:0] conf13; +output [15:0] conf14; +output [15:0] conf15; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [15:0] conf0, conf1, conf2, conf3, conf4, conf5; +reg [15:0] conf6, conf7, conf8, conf9, conf10, conf11; +reg [15:0] conf12, conf13, conf14, conf15; + +//synopsys infer_multibit "conf0" +//synopsys infer_multibit "conf1" +//synopsys infer_multibit "conf2" +//synopsys infer_multibit "conf3" +//synopsys infer_multibit "conf4" +//synopsys infer_multibit "conf5" +//synopsys infer_multibit "conf6" +//synopsys infer_multibit "conf7" +//synopsys infer_multibit "conf8" +//synopsys infer_multibit "conf9" +//synopsys infer_multibit "conf10" +//synopsys infer_multibit "conf11" +//synopsys infer_multibit "conf12" +//synopsys infer_multibit "conf13" +//synopsys infer_multibit "conf14" +//synopsys infer_multibit "conf15" + +wire rf_sel; +reg [15:0] rf_dout; +reg rf_ack; +reg rf_we; + +//////////////////////////////////////////////////////////////////// +// +// Register File Select Logic +// + +assign rf_sel = i_wb_cyc_i & i_wb_stb_i & (i_wb_addr_i[aw-5:aw-8] == rf_addr); + +//////////////////////////////////////////////////////////////////// +// +// Register File Logic +// + +always @(posedge clk_i) + rf_we <= #1 rf_sel & i_wb_we_i & !rf_we; + +always @(posedge clk_i) + rf_ack <= #1 rf_sel & !rf_ack; + +// Writre Logic +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf0 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd0) ) conf0 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf1 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd1) ) conf1 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf2 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd2) ) conf2 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf3 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd3) ) conf3 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf4 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd4) ) conf4 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf5 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd5) ) conf5 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf6 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd6) ) conf6 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf7 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd7) ) conf7 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf8 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd8) ) conf8 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf9 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd9) ) conf9 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf10 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd10) ) conf10 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf11 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd11) ) conf11 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf12 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd12) ) conf12 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf13 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd13) ) conf13 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf14 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd14) ) conf14 <= #1 i_wb_data_i[15:0]; + +always @(posedge clk_i or posedge rst_i) + if(rst_i) conf15 <= #1 16'h0; + else + if(rf_we & (i_wb_addr_i[5:2] == 4'd15) ) conf15 <= #1 i_wb_data_i[15:0]; + +// Read Logic +always @(posedge clk_i) + if(!rf_sel) rf_dout <= #1 16'h0; + else + case(i_wb_addr_i[5:2]) + 4'd0: rf_dout <= #1 conf0; + 4'd1: rf_dout <= #1 conf1; + 4'd2: rf_dout <= #1 conf2; + 4'd3: rf_dout <= #1 conf3; + 4'd4: rf_dout <= #1 conf4; + 4'd5: rf_dout <= #1 conf5; + 4'd6: rf_dout <= #1 conf6; + 4'd7: rf_dout <= #1 conf7; + 4'd8: rf_dout <= #1 conf8; + 4'd9: rf_dout <= #1 conf9; + 4'd10: rf_dout <= #1 conf10; + 4'd11: rf_dout <= #1 conf11; + 4'd12: rf_dout <= #1 conf12; + 4'd13: rf_dout <= #1 conf13; + 4'd14: rf_dout <= #1 conf14; + 4'd15: rf_dout <= #1 conf15; + endcase + +//////////////////////////////////////////////////////////////////// +// +// Register File By-Pass Logic +// + +assign e_wb_addr_o = i_wb_addr_i; +assign e_wb_sel_o = i_wb_sel_i; +assign e_wb_data_o = i_wb_data_i; + +assign e_wb_cyc_o = rf_sel ? 1'b0 : i_wb_cyc_i; +assign e_wb_stb_o = i_wb_stb_i; +assign e_wb_we_o = i_wb_we_i; + +assign i_wb_data_o = rf_sel ? { {aw-16{1'b0}}, rf_dout} : e_wb_data_i; +assign i_wb_ack_o = rf_sel ? rf_ack : e_wb_ack_i; +assign i_wb_err_o = rf_sel ? 1'b0 : e_wb_err_i; +assign i_wb_rty_o = rf_sel ? 1'b0 : e_wb_rty_i; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v new file mode 100644 index 000000000..788d088ac --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v @@ -0,0 +1,449 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Slave Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_slave_if.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_slave_if.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:39 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_slave_if( + + clk_i, rst_i, conf, + + // Slave interface + wb_data_i, wb_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o, + wb_stb_o, wb_ack_i, wb_err_i, wb_rty_i, + + // Master 0 Interface + m0_data_i, m0_data_o, m0_addr_i, m0_sel_i, m0_we_i, m0_cyc_i, + m0_stb_i, m0_ack_o, m0_err_o, m0_rty_o, + + // Master 1 Interface + m1_data_i, m1_data_o, m1_addr_i, m1_sel_i, m1_we_i, m1_cyc_i, + m1_stb_i, m1_ack_o, m1_err_o, m1_rty_o, + + // Master 2 Interface + m2_data_i, m2_data_o, m2_addr_i, m2_sel_i, m2_we_i, m2_cyc_i, + m2_stb_i, m2_ack_o, m2_err_o, m2_rty_o, + + // Master 3 Interface + m3_data_i, m3_data_o, m3_addr_i, m3_sel_i, m3_we_i, m3_cyc_i, + m3_stb_i, m3_ack_o, m3_err_o, m3_rty_o, + + // Master 4 Interface + m4_data_i, m4_data_o, m4_addr_i, m4_sel_i, m4_we_i, m4_cyc_i, + m4_stb_i, m4_ack_o, m4_err_o, m4_rty_o, + + // Master 5 Interface + m5_data_i, m5_data_o, m5_addr_i, m5_sel_i, m5_we_i, m5_cyc_i, + m5_stb_i, m5_ack_o, m5_err_o, m5_rty_o, + + // Master 6 Interface + m6_data_i, m6_data_o, m6_addr_i, m6_sel_i, m6_we_i, m6_cyc_i, + m6_stb_i, m6_ack_o, m6_err_o, m6_rty_o, + + // Master 7 Interface + m7_data_i, m7_data_o, m7_addr_i, m7_sel_i, m7_we_i, m7_cyc_i, + m7_stb_i, m7_ack_o, m7_err_o, m7_rty_o + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter [1:0] pri_sel = 2'd2; +parameter aw = 32; // Address bus Width +parameter dw = 32; // Data bus Width +parameter sw = dw / 8; // Number of Select Lines + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; +input [15:0] conf; + +// Slave Interface +input [dw-1:0] wb_data_i; +output [dw-1:0] wb_data_o; +output [aw-1:0] wb_addr_o; +output [sw-1:0] wb_sel_o; +output wb_we_o; +output wb_cyc_o; +output wb_stb_o; +input wb_ack_i; +input wb_err_i; +input wb_rty_i; + +// Master 0 Interface +input [dw-1:0] m0_data_i; +output [dw-1:0] m0_data_o; +input [aw-1:0] m0_addr_i; +input [sw-1:0] m0_sel_i; +input m0_we_i; +input m0_cyc_i; +input m0_stb_i; +output m0_ack_o; +output m0_err_o; +output m0_rty_o; + +// Master 1 Interface +input [dw-1:0] m1_data_i; +output [dw-1:0] m1_data_o; +input [aw-1:0] m1_addr_i; +input [sw-1:0] m1_sel_i; +input m1_we_i; +input m1_cyc_i; +input m1_stb_i; +output m1_ack_o; +output m1_err_o; +output m1_rty_o; + +// Master 2 Interface +input [dw-1:0] m2_data_i; +output [dw-1:0] m2_data_o; +input [aw-1:0] m2_addr_i; +input [sw-1:0] m2_sel_i; +input m2_we_i; +input m2_cyc_i; +input m2_stb_i; +output m2_ack_o; +output m2_err_o; +output m2_rty_o; + +// Master 3 Interface +input [dw-1:0] m3_data_i; +output [dw-1:0] m3_data_o; +input [aw-1:0] m3_addr_i; +input [sw-1:0] m3_sel_i; +input m3_we_i; +input m3_cyc_i; +input m3_stb_i; +output m3_ack_o; +output m3_err_o; +output m3_rty_o; + +// Master 4 Interface +input [dw-1:0] m4_data_i; +output [dw-1:0] m4_data_o; +input [aw-1:0] m4_addr_i; +input [sw-1:0] m4_sel_i; +input m4_we_i; +input m4_cyc_i; +input m4_stb_i; +output m4_ack_o; +output m4_err_o; +output m4_rty_o; + +// Master 5 Interface +input [dw-1:0] m5_data_i; +output [dw-1:0] m5_data_o; +input [aw-1:0] m5_addr_i; +input [sw-1:0] m5_sel_i; +input m5_we_i; +input m5_cyc_i; +input m5_stb_i; +output m5_ack_o; +output m5_err_o; +output m5_rty_o; + +// Master 6 Interface +input [dw-1:0] m6_data_i; +output [dw-1:0] m6_data_o; +input [aw-1:0] m6_addr_i; +input [sw-1:0] m6_sel_i; +input m6_we_i; +input m6_cyc_i; +input m6_stb_i; +output m6_ack_o; +output m6_err_o; +output m6_rty_o; + +// Master 7 Interface +input [dw-1:0] m7_data_i; +output [dw-1:0] m7_data_o; +input [aw-1:0] m7_addr_i; +input [sw-1:0] m7_sel_i; +input m7_we_i; +input m7_cyc_i; +input m7_stb_i; +output m7_ack_o; +output m7_err_o; +output m7_rty_o; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [aw-1:0] wb_addr_o; +reg [dw-1:0] wb_data_o; +reg [sw-1:0] wb_sel_o; +reg wb_we_o; +reg wb_cyc_o; +reg wb_stb_o; +wire [2:0] mast_sel_simple; +wire [2:0] mast_sel_pe; +wire [2:0] mast_sel; + +reg next; +reg m0_cyc_r, m1_cyc_r, m2_cyc_r, m3_cyc_r; +reg m4_cyc_r, m5_cyc_r, m6_cyc_r, m7_cyc_r; + +//////////////////////////////////////////////////////////////////// +// +// Select logic +// + +always @(posedge clk_i) + next <= #1 ~wb_cyc_o; + + +wb_conmax_arb arb( + .clk( clk_i ), + .rst( rst_i ), + .req( { m7_cyc_i, + m6_cyc_i, + m5_cyc_i, + m4_cyc_i, + m3_cyc_i, + m2_cyc_i, + m1_cyc_i, + m0_cyc_i } ), + .gnt( mast_sel_simple ), + .next( 1'b0 ) + ); + +wb_conmax_msel #(pri_sel) msel( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf ), + .req( { m7_cyc_i, + m6_cyc_i, + m5_cyc_i, + m4_cyc_i, + m3_cyc_i, + m2_cyc_i, + m1_cyc_i, + m0_cyc_i} ), + .sel( mast_sel_pe ), + .next( next ) + ); + +assign mast_sel = (pri_sel == 2'd0) ? mast_sel_simple : mast_sel_pe; + +//////////////////////////////////////////////////////////////////// +// +// Address & Data Pass +// + +always @(mast_sel or m0_addr_i or m1_addr_i or m2_addr_i or m3_addr_i + or m4_addr_i or m5_addr_i or m6_addr_i or m7_addr_i) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_addr_o = m0_addr_i; + 3'd1: wb_addr_o = m1_addr_i; + 3'd2: wb_addr_o = m2_addr_i; + 3'd3: wb_addr_o = m3_addr_i; + 3'd4: wb_addr_o = m4_addr_i; + 3'd5: wb_addr_o = m5_addr_i; + 3'd6: wb_addr_o = m6_addr_i; + 3'd7: wb_addr_o = m7_addr_i; + default: wb_addr_o = {aw{1'bx}}; + endcase + +always @(mast_sel or m0_sel_i or m1_sel_i or m2_sel_i or m3_sel_i + or m4_sel_i or m5_sel_i or m6_sel_i or m7_sel_i) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_sel_o = m0_sel_i; + 3'd1: wb_sel_o = m1_sel_i; + 3'd2: wb_sel_o = m2_sel_i; + 3'd3: wb_sel_o = m3_sel_i; + 3'd4: wb_sel_o = m4_sel_i; + 3'd5: wb_sel_o = m5_sel_i; + 3'd6: wb_sel_o = m6_sel_i; + 3'd7: wb_sel_o = m7_sel_i; + default: wb_sel_o = {sw{1'bx}}; + endcase + +always @(mast_sel or m0_data_i or m1_data_i or m2_data_i or m3_data_i + or m4_data_i or m5_data_i or m6_data_i or m7_data_i) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_data_o = m0_data_i; + 3'd1: wb_data_o = m1_data_i; + 3'd2: wb_data_o = m2_data_i; + 3'd3: wb_data_o = m3_data_i; + 3'd4: wb_data_o = m4_data_i; + 3'd5: wb_data_o = m5_data_i; + 3'd6: wb_data_o = m6_data_i; + 3'd7: wb_data_o = m7_data_i; + default: wb_data_o = {dw{1'bx}}; + endcase + +assign m0_data_o = wb_data_i; +assign m1_data_o = wb_data_i; +assign m2_data_o = wb_data_i; +assign m3_data_o = wb_data_i; +assign m4_data_o = wb_data_i; +assign m5_data_o = wb_data_i; +assign m6_data_o = wb_data_i; +assign m7_data_o = wb_data_i; + +//////////////////////////////////////////////////////////////////// +// +// Control Signal Pass +// + +always @(mast_sel or m0_we_i or m1_we_i or m2_we_i or m3_we_i + or m4_we_i or m5_we_i or m6_we_i or m7_we_i) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_we_o = m0_we_i; + 3'd1: wb_we_o = m1_we_i; + 3'd2: wb_we_o = m2_we_i; + 3'd3: wb_we_o = m3_we_i; + 3'd4: wb_we_o = m4_we_i; + 3'd5: wb_we_o = m5_we_i; + 3'd6: wb_we_o = m6_we_i; + 3'd7: wb_we_o = m7_we_i; + default: wb_we_o = 1'bx; + endcase + +always @(posedge clk_i) + m0_cyc_r <= #1 m0_cyc_i; + +always @(posedge clk_i) + m1_cyc_r <= #1 m1_cyc_i; + +always @(posedge clk_i) + m2_cyc_r <= #1 m2_cyc_i; + +always @(posedge clk_i) + m3_cyc_r <= #1 m3_cyc_i; + +always @(posedge clk_i) + m4_cyc_r <= #1 m4_cyc_i; + +always @(posedge clk_i) + m5_cyc_r <= #1 m5_cyc_i; + +always @(posedge clk_i) + m6_cyc_r <= #1 m6_cyc_i; + +always @(posedge clk_i) + m7_cyc_r <= #1 m7_cyc_i; + +always @(mast_sel or m0_cyc_i or m1_cyc_i or m2_cyc_i or m3_cyc_i + or m4_cyc_i or m5_cyc_i or m6_cyc_i or m7_cyc_i + or m0_cyc_r or m1_cyc_r or m2_cyc_r or m3_cyc_r + or m4_cyc_r or m5_cyc_r or m6_cyc_r or m7_cyc_r) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_cyc_o = m0_cyc_i & m0_cyc_r; + 3'd1: wb_cyc_o = m1_cyc_i & m1_cyc_r; + 3'd2: wb_cyc_o = m2_cyc_i & m2_cyc_r; + 3'd3: wb_cyc_o = m3_cyc_i & m3_cyc_r; + 3'd4: wb_cyc_o = m4_cyc_i & m4_cyc_r; + 3'd5: wb_cyc_o = m5_cyc_i & m5_cyc_r; + 3'd6: wb_cyc_o = m6_cyc_i & m6_cyc_r; + 3'd7: wb_cyc_o = m7_cyc_i & m7_cyc_r; + default: wb_cyc_o = 1'b0; + endcase + +always @(mast_sel or m0_stb_i or m1_stb_i or m2_stb_i or m3_stb_i + or m4_stb_i or m5_stb_i or m6_stb_i or m7_stb_i) + case(mast_sel) // synopsys parallel_case + 3'd0: wb_stb_o = m0_stb_i; + 3'd1: wb_stb_o = m1_stb_i; + 3'd2: wb_stb_o = m2_stb_i; + 3'd3: wb_stb_o = m3_stb_i; + 3'd4: wb_stb_o = m4_stb_i; + 3'd5: wb_stb_o = m5_stb_i; + 3'd6: wb_stb_o = m6_stb_i; + 3'd7: wb_stb_o = m7_stb_i; + default: wb_stb_o = 1'b0; + endcase + +assign m0_ack_o = (mast_sel==3'd0) & wb_ack_i; +assign m1_ack_o = (mast_sel==3'd1) & wb_ack_i; +assign m2_ack_o = (mast_sel==3'd2) & wb_ack_i; +assign m3_ack_o = (mast_sel==3'd3) & wb_ack_i; +assign m4_ack_o = (mast_sel==3'd4) & wb_ack_i; +assign m5_ack_o = (mast_sel==3'd5) & wb_ack_i; +assign m6_ack_o = (mast_sel==3'd6) & wb_ack_i; +assign m7_ack_o = (mast_sel==3'd7) & wb_ack_i; + +assign m0_err_o = (mast_sel==3'd0) & wb_err_i; +assign m1_err_o = (mast_sel==3'd1) & wb_err_i; +assign m2_err_o = (mast_sel==3'd2) & wb_err_i; +assign m3_err_o = (mast_sel==3'd3) & wb_err_i; +assign m4_err_o = (mast_sel==3'd4) & wb_err_i; +assign m5_err_o = (mast_sel==3'd5) & wb_err_i; +assign m6_err_o = (mast_sel==3'd6) & wb_err_i; +assign m7_err_o = (mast_sel==3'd7) & wb_err_i; + +assign m0_rty_o = (mast_sel==3'd0) & wb_rty_i; +assign m1_rty_o = (mast_sel==3'd1) & wb_rty_i; +assign m2_rty_o = (mast_sel==3'd2) & wb_rty_i; +assign m3_rty_o = (mast_sel==3'd3) & wb_rty_i; +assign m4_rty_o = (mast_sel==3'd4) & wb_rty_i; +assign m5_rty_o = (mast_sel==3'd5) & wb_rty_i; +assign m6_rty_o = (mast_sel==3'd6) & wb_rty_i; +assign m7_rty_o = (mast_sel==3'd7) & wb_rty_i; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v new file mode 100644 index 000000000..524d5eb08 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v @@ -0,0 +1,4806 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE Connection Matrix Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_conmax_top.v,v 1.2 2002/10/03 05:40:07 rudi Exp $ +// +// $Date: 2002/10/03 05:40:07 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_conmax_top.v,v $ +// Revision 1.2 2002/10/03 05:40:07 rudi +// Fixed a minor bug in parameter passing, updated headers and specification. +// +// Revision 1.1.1.1 2001/10/19 11:01:38 rudi +// WISHBONE CONMAX IP Core +// +// +// +// +// + +`include "wb_conmax_defines.v" + +module wb_conmax_top( + clk_i, rst_i, + + // Master 0 Interface + m0_data_i, m0_data_o, m0_addr_i, m0_sel_i, m0_we_i, m0_cyc_i, + m0_stb_i, m0_ack_o, m0_err_o, m0_rty_o, + + // Master 1 Interface + m1_data_i, m1_data_o, m1_addr_i, m1_sel_i, m1_we_i, m1_cyc_i, + m1_stb_i, m1_ack_o, m1_err_o, m1_rty_o, + + // Master 2 Interface + m2_data_i, m2_data_o, m2_addr_i, m2_sel_i, m2_we_i, m2_cyc_i, + m2_stb_i, m2_ack_o, m2_err_o, m2_rty_o, + + // Master 3 Interface + m3_data_i, m3_data_o, m3_addr_i, m3_sel_i, m3_we_i, m3_cyc_i, + m3_stb_i, m3_ack_o, m3_err_o, m3_rty_o, + + // Master 4 Interface + m4_data_i, m4_data_o, m4_addr_i, m4_sel_i, m4_we_i, m4_cyc_i, + m4_stb_i, m4_ack_o, m4_err_o, m4_rty_o, + + // Master 5 Interface + m5_data_i, m5_data_o, m5_addr_i, m5_sel_i, m5_we_i, m5_cyc_i, + m5_stb_i, m5_ack_o, m5_err_o, m5_rty_o, + + // Master 6 Interface + m6_data_i, m6_data_o, m6_addr_i, m6_sel_i, m6_we_i, m6_cyc_i, + m6_stb_i, m6_ack_o, m6_err_o, m6_rty_o, + + // Master 7 Interface + m7_data_i, m7_data_o, m7_addr_i, m7_sel_i, m7_we_i, m7_cyc_i, + m7_stb_i, m7_ack_o, m7_err_o, m7_rty_o, + + // Slave 0 Interface + s0_data_i, s0_data_o, s0_addr_o, s0_sel_o, s0_we_o, s0_cyc_o, + s0_stb_o, s0_ack_i, s0_err_i, s0_rty_i, + + // Slave 1 Interface + s1_data_i, s1_data_o, s1_addr_o, s1_sel_o, s1_we_o, s1_cyc_o, + s1_stb_o, s1_ack_i, s1_err_i, s1_rty_i, + + // Slave 2 Interface + s2_data_i, s2_data_o, s2_addr_o, s2_sel_o, s2_we_o, s2_cyc_o, + s2_stb_o, s2_ack_i, s2_err_i, s2_rty_i, + + // Slave 3 Interface + s3_data_i, s3_data_o, s3_addr_o, s3_sel_o, s3_we_o, s3_cyc_o, + s3_stb_o, s3_ack_i, s3_err_i, s3_rty_i, + + // Slave 4 Interface + s4_data_i, s4_data_o, s4_addr_o, s4_sel_o, s4_we_o, s4_cyc_o, + s4_stb_o, s4_ack_i, s4_err_i, s4_rty_i, + + // Slave 5 Interface + s5_data_i, s5_data_o, s5_addr_o, s5_sel_o, s5_we_o, s5_cyc_o, + s5_stb_o, s5_ack_i, s5_err_i, s5_rty_i, + + // Slave 6 Interface + s6_data_i, s6_data_o, s6_addr_o, s6_sel_o, s6_we_o, s6_cyc_o, + s6_stb_o, s6_ack_i, s6_err_i, s6_rty_i, + + // Slave 7 Interface + s7_data_i, s7_data_o, s7_addr_o, s7_sel_o, s7_we_o, s7_cyc_o, + s7_stb_o, s7_ack_i, s7_err_i, s7_rty_i, + + // Slave 8 Interface + s8_data_i, s8_data_o, s8_addr_o, s8_sel_o, s8_we_o, s8_cyc_o, + s8_stb_o, s8_ack_i, s8_err_i, s8_rty_i, + + // Slave 9 Interface + s9_data_i, s9_data_o, s9_addr_o, s9_sel_o, s9_we_o, s9_cyc_o, + s9_stb_o, s9_ack_i, s9_err_i, s9_rty_i, + + // Slave 10 Interface + s10_data_i, s10_data_o, s10_addr_o, s10_sel_o, s10_we_o, s10_cyc_o, + s10_stb_o, s10_ack_i, s10_err_i, s10_rty_i, + + // Slave 11 Interface + s11_data_i, s11_data_o, s11_addr_o, s11_sel_o, s11_we_o, s11_cyc_o, + s11_stb_o, s11_ack_i, s11_err_i, s11_rty_i, + + // Slave 12 Interface + s12_data_i, s12_data_o, s12_addr_o, s12_sel_o, s12_we_o, s12_cyc_o, + s12_stb_o, s12_ack_i, s12_err_i, s12_rty_i, + + // Slave 13 Interface + s13_data_i, s13_data_o, s13_addr_o, s13_sel_o, s13_we_o, s13_cyc_o, + s13_stb_o, s13_ack_i, s13_err_i, s13_rty_i, + + // Slave 14 Interface + s14_data_i, s14_data_o, s14_addr_o, s14_sel_o, s14_we_o, s14_cyc_o, + s14_stb_o, s14_ack_i, s14_err_i, s14_rty_i, + + // Slave 15 Interface + s15_data_i, s15_data_o, s15_addr_o, s15_sel_o, s15_we_o, s15_cyc_o, + s15_stb_o, s15_ack_i, s15_err_i, s15_rty_i + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +parameter dw = 32; // Data bus Width +parameter aw = 32; // Address bus Width +parameter [3:0] rf_addr = 4'hf; +parameter [1:0] pri_sel0 = 2'd2; +parameter [1:0] pri_sel1 = 2'd2; +parameter [1:0] pri_sel2 = 2'd2; +parameter [1:0] pri_sel3 = 2'd2; +parameter [1:0] pri_sel4 = 2'd2; +parameter [1:0] pri_sel5 = 2'd2; +parameter [1:0] pri_sel6 = 2'd2; +parameter [1:0] pri_sel7 = 2'd2; +parameter [1:0] pri_sel8 = 2'd2; +parameter [1:0] pri_sel9 = 2'd2; +parameter [1:0] pri_sel10 = 2'd2; +parameter [1:0] pri_sel11 = 2'd2; +parameter [1:0] pri_sel12 = 2'd2; +parameter [1:0] pri_sel13 = 2'd2; +parameter [1:0] pri_sel14 = 2'd2; +parameter [1:0] pri_sel15 = 2'd2; + +parameter sw = dw / 8; // Number of Select Lines + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; + +// Master 0 Interface +input [dw-1:0] m0_data_i; +output [dw-1:0] m0_data_o; +input [aw-1:0] m0_addr_i; +input [sw-1:0] m0_sel_i; +input m0_we_i; +input m0_cyc_i; +input m0_stb_i; +output m0_ack_o; +output m0_err_o; +output m0_rty_o; + +// Master 1 Interface +input [dw-1:0] m1_data_i; +output [dw-1:0] m1_data_o; +input [aw-1:0] m1_addr_i; +input [sw-1:0] m1_sel_i; +input m1_we_i; +input m1_cyc_i; +input m1_stb_i; +output m1_ack_o; +output m1_err_o; +output m1_rty_o; + +// Master 2 Interface +input [dw-1:0] m2_data_i; +output [dw-1:0] m2_data_o; +input [aw-1:0] m2_addr_i; +input [sw-1:0] m2_sel_i; +input m2_we_i; +input m2_cyc_i; +input m2_stb_i; +output m2_ack_o; +output m2_err_o; +output m2_rty_o; + +// Master 3 Interface +input [dw-1:0] m3_data_i; +output [dw-1:0] m3_data_o; +input [aw-1:0] m3_addr_i; +input [sw-1:0] m3_sel_i; +input m3_we_i; +input m3_cyc_i; +input m3_stb_i; +output m3_ack_o; +output m3_err_o; +output m3_rty_o; + +// Master 4 Interface +input [dw-1:0] m4_data_i; +output [dw-1:0] m4_data_o; +input [aw-1:0] m4_addr_i; +input [sw-1:0] m4_sel_i; +input m4_we_i; +input m4_cyc_i; +input m4_stb_i; +output m4_ack_o; +output m4_err_o; +output m4_rty_o; + +// Master 5 Interface +input [dw-1:0] m5_data_i; +output [dw-1:0] m5_data_o; +input [aw-1:0] m5_addr_i; +input [sw-1:0] m5_sel_i; +input m5_we_i; +input m5_cyc_i; +input m5_stb_i; +output m5_ack_o; +output m5_err_o; +output m5_rty_o; + +// Master 6 Interface +input [dw-1:0] m6_data_i; +output [dw-1:0] m6_data_o; +input [aw-1:0] m6_addr_i; +input [sw-1:0] m6_sel_i; +input m6_we_i; +input m6_cyc_i; +input m6_stb_i; +output m6_ack_o; +output m6_err_o; +output m6_rty_o; + +// Master 7 Interface +input [dw-1:0] m7_data_i; +output [dw-1:0] m7_data_o; +input [aw-1:0] m7_addr_i; +input [sw-1:0] m7_sel_i; +input m7_we_i; +input m7_cyc_i; +input m7_stb_i; +output m7_ack_o; +output m7_err_o; +output m7_rty_o; + +// Slave 0 Interface +input [dw-1:0] s0_data_i; +output [dw-1:0] s0_data_o; +output [aw-1:0] s0_addr_o; +output [sw-1:0] s0_sel_o; +output s0_we_o; +output s0_cyc_o; +output s0_stb_o; +input s0_ack_i; +input s0_err_i; +input s0_rty_i; + +// Slave 1 Interface +input [dw-1:0] s1_data_i; +output [dw-1:0] s1_data_o; +output [aw-1:0] s1_addr_o; +output [sw-1:0] s1_sel_o; +output s1_we_o; +output s1_cyc_o; +output s1_stb_o; +input s1_ack_i; +input s1_err_i; +input s1_rty_i; + +// Slave 2 Interface +input [dw-1:0] s2_data_i; +output [dw-1:0] s2_data_o; +output [aw-1:0] s2_addr_o; +output [sw-1:0] s2_sel_o; +output s2_we_o; +output s2_cyc_o; +output s2_stb_o; +input s2_ack_i; +input s2_err_i; +input s2_rty_i; + +// Slave 3 Interface +input [dw-1:0] s3_data_i; +output [dw-1:0] s3_data_o; +output [aw-1:0] s3_addr_o; +output [sw-1:0] s3_sel_o; +output s3_we_o; +output s3_cyc_o; +output s3_stb_o; +input s3_ack_i; +input s3_err_i; +input s3_rty_i; + +// Slave 4 Interface +input [dw-1:0] s4_data_i; +output [dw-1:0] s4_data_o; +output [aw-1:0] s4_addr_o; +output [sw-1:0] s4_sel_o; +output s4_we_o; +output s4_cyc_o; +output s4_stb_o; +input s4_ack_i; +input s4_err_i; +input s4_rty_i; + +// Slave 5 Interface +input [dw-1:0] s5_data_i; +output [dw-1:0] s5_data_o; +output [aw-1:0] s5_addr_o; +output [sw-1:0] s5_sel_o; +output s5_we_o; +output s5_cyc_o; +output s5_stb_o; +input s5_ack_i; +input s5_err_i; +input s5_rty_i; + +// Slave 6 Interface +input [dw-1:0] s6_data_i; +output [dw-1:0] s6_data_o; +output [aw-1:0] s6_addr_o; +output [sw-1:0] s6_sel_o; +output s6_we_o; +output s6_cyc_o; +output s6_stb_o; +input s6_ack_i; +input s6_err_i; +input s6_rty_i; + +// Slave 7 Interface +input [dw-1:0] s7_data_i; +output [dw-1:0] s7_data_o; +output [aw-1:0] s7_addr_o; +output [sw-1:0] s7_sel_o; +output s7_we_o; +output s7_cyc_o; +output s7_stb_o; +input s7_ack_i; +input s7_err_i; +input s7_rty_i; + +// Slave 8 Interface +input [dw-1:0] s8_data_i; +output [dw-1:0] s8_data_o; +output [aw-1:0] s8_addr_o; +output [sw-1:0] s8_sel_o; +output s8_we_o; +output s8_cyc_o; +output s8_stb_o; +input s8_ack_i; +input s8_err_i; +input s8_rty_i; + +// Slave 9 Interface +input [dw-1:0] s9_data_i; +output [dw-1:0] s9_data_o; +output [aw-1:0] s9_addr_o; +output [sw-1:0] s9_sel_o; +output s9_we_o; +output s9_cyc_o; +output s9_stb_o; +input s9_ack_i; +input s9_err_i; +input s9_rty_i; + +// Slave 10 Interface +input [dw-1:0] s10_data_i; +output [dw-1:0] s10_data_o; +output [aw-1:0] s10_addr_o; +output [sw-1:0] s10_sel_o; +output s10_we_o; +output s10_cyc_o; +output s10_stb_o; +input s10_ack_i; +input s10_err_i; +input s10_rty_i; + +// Slave 11 Interface +input [dw-1:0] s11_data_i; +output [dw-1:0] s11_data_o; +output [aw-1:0] s11_addr_o; +output [sw-1:0] s11_sel_o; +output s11_we_o; +output s11_cyc_o; +output s11_stb_o; +input s11_ack_i; +input s11_err_i; +input s11_rty_i; + +// Slave 12 Interface +input [dw-1:0] s12_data_i; +output [dw-1:0] s12_data_o; +output [aw-1:0] s12_addr_o; +output [sw-1:0] s12_sel_o; +output s12_we_o; +output s12_cyc_o; +output s12_stb_o; +input s12_ack_i; +input s12_err_i; +input s12_rty_i; + +// Slave 13 Interface +input [dw-1:0] s13_data_i; +output [dw-1:0] s13_data_o; +output [aw-1:0] s13_addr_o; +output [sw-1:0] s13_sel_o; +output s13_we_o; +output s13_cyc_o; +output s13_stb_o; +input s13_ack_i; +input s13_err_i; +input s13_rty_i; + +// Slave 14 Interface +input [dw-1:0] s14_data_i; +output [dw-1:0] s14_data_o; +output [aw-1:0] s14_addr_o; +output [sw-1:0] s14_sel_o; +output s14_we_o; +output s14_cyc_o; +output s14_stb_o; +input s14_ack_i; +input s14_err_i; +input s14_rty_i; + +// Slave 15 Interface +input [dw-1:0] s15_data_i; +output [dw-1:0] s15_data_o; +output [aw-1:0] s15_addr_o; +output [sw-1:0] s15_sel_o; +output s15_we_o; +output s15_cyc_o; +output s15_stb_o; +input s15_ack_i; +input s15_err_i; +input s15_rty_i; + +//////////////////////////////////////////////////////////////////// +// +// Local wires +// + +wire [dw-1:0] i_s15_data_i; +wire [dw-1:0] i_s15_data_o; +wire [aw-1:0] i_s15_addr_o; +wire [sw-1:0] i_s15_sel_o; +wire i_s15_we_o; +wire i_s15_cyc_o; +wire i_s15_stb_o; +wire i_s15_ack_i; +wire i_s15_err_i; +wire i_s15_rty_i; + +wire [dw-1:0] m0s0_data_i; +wire [dw-1:0] m0s0_data_o; +wire [aw-1:0] m0s0_addr; +wire [sw-1:0] m0s0_sel; +wire m0s0_we; +wire m0s0_cyc; +wire m0s0_stb; +wire m0s0_ack; +wire m0s0_err; +wire m0s0_rty; +wire [dw-1:0] m0s1_data_i; +wire [dw-1:0] m0s1_data_o; +wire [aw-1:0] m0s1_addr; +wire [sw-1:0] m0s1_sel; +wire m0s1_we; +wire m0s1_cyc; +wire m0s1_stb; +wire m0s1_ack; +wire m0s1_err; +wire m0s1_rty; +wire [dw-1:0] m0s2_data_i; +wire [dw-1:0] m0s2_data_o; +wire [aw-1:0] m0s2_addr; +wire [sw-1:0] m0s2_sel; +wire m0s2_we; +wire m0s2_cyc; +wire m0s2_stb; +wire m0s2_ack; +wire m0s2_err; +wire m0s2_rty; +wire [dw-1:0] m0s3_data_i; +wire [dw-1:0] m0s3_data_o; +wire [aw-1:0] m0s3_addr; +wire [sw-1:0] m0s3_sel; +wire m0s3_we; +wire m0s3_cyc; +wire m0s3_stb; +wire m0s3_ack; +wire m0s3_err; +wire m0s3_rty; +wire [dw-1:0] m0s4_data_i; +wire [dw-1:0] m0s4_data_o; +wire [aw-1:0] m0s4_addr; +wire [sw-1:0] m0s4_sel; +wire m0s4_we; +wire m0s4_cyc; +wire m0s4_stb; +wire m0s4_ack; +wire m0s4_err; +wire m0s4_rty; +wire [dw-1:0] m0s5_data_i; +wire [dw-1:0] m0s5_data_o; +wire [aw-1:0] m0s5_addr; +wire [sw-1:0] m0s5_sel; +wire m0s5_we; +wire m0s5_cyc; +wire m0s5_stb; +wire m0s5_ack; +wire m0s5_err; +wire m0s5_rty; +wire [dw-1:0] m0s6_data_i; +wire [dw-1:0] m0s6_data_o; +wire [aw-1:0] m0s6_addr; +wire [sw-1:0] m0s6_sel; +wire m0s6_we; +wire m0s6_cyc; +wire m0s6_stb; +wire m0s6_ack; +wire m0s6_err; +wire m0s6_rty; +wire [dw-1:0] m0s7_data_i; +wire [dw-1:0] m0s7_data_o; +wire [aw-1:0] m0s7_addr; +wire [sw-1:0] m0s7_sel; +wire m0s7_we; +wire m0s7_cyc; +wire m0s7_stb; +wire m0s7_ack; +wire m0s7_err; +wire m0s7_rty; +wire [dw-1:0] m0s8_data_i; +wire [dw-1:0] m0s8_data_o; +wire [aw-1:0] m0s8_addr; +wire [sw-1:0] m0s8_sel; +wire m0s8_we; +wire m0s8_cyc; +wire m0s8_stb; +wire m0s8_ack; +wire m0s8_err; +wire m0s8_rty; +wire [dw-1:0] m0s9_data_i; +wire [dw-1:0] m0s9_data_o; +wire [aw-1:0] m0s9_addr; +wire [sw-1:0] m0s9_sel; +wire m0s9_we; +wire m0s9_cyc; +wire m0s9_stb; +wire m0s9_ack; +wire m0s9_err; +wire m0s9_rty; +wire [dw-1:0] m0s10_data_i; +wire [dw-1:0] m0s10_data_o; +wire [aw-1:0] m0s10_addr; +wire [sw-1:0] m0s10_sel; +wire m0s10_we; +wire m0s10_cyc; +wire m0s10_stb; +wire m0s10_ack; +wire m0s10_err; +wire m0s10_rty; +wire [dw-1:0] m0s11_data_i; +wire [dw-1:0] m0s11_data_o; +wire [aw-1:0] m0s11_addr; +wire [sw-1:0] m0s11_sel; +wire m0s11_we; +wire m0s11_cyc; +wire m0s11_stb; +wire m0s11_ack; +wire m0s11_err; +wire m0s11_rty; +wire [dw-1:0] m0s12_data_i; +wire [dw-1:0] m0s12_data_o; +wire [aw-1:0] m0s12_addr; +wire [sw-1:0] m0s12_sel; +wire m0s12_we; +wire m0s12_cyc; +wire m0s12_stb; +wire m0s12_ack; +wire m0s12_err; +wire m0s12_rty; +wire [dw-1:0] m0s13_data_i; +wire [dw-1:0] m0s13_data_o; +wire [aw-1:0] m0s13_addr; +wire [sw-1:0] m0s13_sel; +wire m0s13_we; +wire m0s13_cyc; +wire m0s13_stb; +wire m0s13_ack; +wire m0s13_err; +wire m0s13_rty; +wire [dw-1:0] m0s14_data_i; +wire [dw-1:0] m0s14_data_o; +wire [aw-1:0] m0s14_addr; +wire [sw-1:0] m0s14_sel; +wire m0s14_we; +wire m0s14_cyc; +wire m0s14_stb; +wire m0s14_ack; +wire m0s14_err; +wire m0s14_rty; +wire [dw-1:0] m0s15_data_i; +wire [dw-1:0] m0s15_data_o; +wire [aw-1:0] m0s15_addr; +wire [sw-1:0] m0s15_sel; +wire m0s15_we; +wire m0s15_cyc; +wire m0s15_stb; +wire m0s15_ack; +wire m0s15_err; +wire m0s15_rty; +wire [dw-1:0] m1s0_data_i; +wire [dw-1:0] m1s0_data_o; +wire [aw-1:0] m1s0_addr; +wire [sw-1:0] m1s0_sel; +wire m1s0_we; +wire m1s0_cyc; +wire m1s0_stb; +wire m1s0_ack; +wire m1s0_err; +wire m1s0_rty; +wire [dw-1:0] m1s1_data_i; +wire [dw-1:0] m1s1_data_o; +wire [aw-1:0] m1s1_addr; +wire [sw-1:0] m1s1_sel; +wire m1s1_we; +wire m1s1_cyc; +wire m1s1_stb; +wire m1s1_ack; +wire m1s1_err; +wire m1s1_rty; +wire [dw-1:0] m1s2_data_i; +wire [dw-1:0] m1s2_data_o; +wire [aw-1:0] m1s2_addr; +wire [sw-1:0] m1s2_sel; +wire m1s2_we; +wire m1s2_cyc; +wire m1s2_stb; +wire m1s2_ack; +wire m1s2_err; +wire m1s2_rty; +wire [dw-1:0] m1s3_data_i; +wire [dw-1:0] m1s3_data_o; +wire [aw-1:0] m1s3_addr; +wire [sw-1:0] m1s3_sel; +wire m1s3_we; +wire m1s3_cyc; +wire m1s3_stb; +wire m1s3_ack; +wire m1s3_err; +wire m1s3_rty; +wire [dw-1:0] m1s4_data_i; +wire [dw-1:0] m1s4_data_o; +wire [aw-1:0] m1s4_addr; +wire [sw-1:0] m1s4_sel; +wire m1s4_we; +wire m1s4_cyc; +wire m1s4_stb; +wire m1s4_ack; +wire m1s4_err; +wire m1s4_rty; +wire [dw-1:0] m1s5_data_i; +wire [dw-1:0] m1s5_data_o; +wire [aw-1:0] m1s5_addr; +wire [sw-1:0] m1s5_sel; +wire m1s5_we; +wire m1s5_cyc; +wire m1s5_stb; +wire m1s5_ack; +wire m1s5_err; +wire m1s5_rty; +wire [dw-1:0] m1s6_data_i; +wire [dw-1:0] m1s6_data_o; +wire [aw-1:0] m1s6_addr; +wire [sw-1:0] m1s6_sel; +wire m1s6_we; +wire m1s6_cyc; +wire m1s6_stb; +wire m1s6_ack; +wire m1s6_err; +wire m1s6_rty; +wire [dw-1:0] m1s7_data_i; +wire [dw-1:0] m1s7_data_o; +wire [aw-1:0] m1s7_addr; +wire [sw-1:0] m1s7_sel; +wire m1s7_we; +wire m1s7_cyc; +wire m1s7_stb; +wire m1s7_ack; +wire m1s7_err; +wire m1s7_rty; +wire [dw-1:0] m1s8_data_i; +wire [dw-1:0] m1s8_data_o; +wire [aw-1:0] m1s8_addr; +wire [sw-1:0] m1s8_sel; +wire m1s8_we; +wire m1s8_cyc; +wire m1s8_stb; +wire m1s8_ack; +wire m1s8_err; +wire m1s8_rty; +wire [dw-1:0] m1s9_data_i; +wire [dw-1:0] m1s9_data_o; +wire [aw-1:0] m1s9_addr; +wire [sw-1:0] m1s9_sel; +wire m1s9_we; +wire m1s9_cyc; +wire m1s9_stb; +wire m1s9_ack; +wire m1s9_err; +wire m1s9_rty; +wire [dw-1:0] m1s10_data_i; +wire [dw-1:0] m1s10_data_o; +wire [aw-1:0] m1s10_addr; +wire [sw-1:0] m1s10_sel; +wire m1s10_we; +wire m1s10_cyc; +wire m1s10_stb; +wire m1s10_ack; +wire m1s10_err; +wire m1s10_rty; +wire [dw-1:0] m1s11_data_i; +wire [dw-1:0] m1s11_data_o; +wire [aw-1:0] m1s11_addr; +wire [sw-1:0] m1s11_sel; +wire m1s11_we; +wire m1s11_cyc; +wire m1s11_stb; +wire m1s11_ack; +wire m1s11_err; +wire m1s11_rty; +wire [dw-1:0] m1s12_data_i; +wire [dw-1:0] m1s12_data_o; +wire [aw-1:0] m1s12_addr; +wire [sw-1:0] m1s12_sel; +wire m1s12_we; +wire m1s12_cyc; +wire m1s12_stb; +wire m1s12_ack; +wire m1s12_err; +wire m1s12_rty; +wire [dw-1:0] m1s13_data_i; +wire [dw-1:0] m1s13_data_o; +wire [aw-1:0] m1s13_addr; +wire [sw-1:0] m1s13_sel; +wire m1s13_we; +wire m1s13_cyc; +wire m1s13_stb; +wire m1s13_ack; +wire m1s13_err; +wire m1s13_rty; +wire [dw-1:0] m1s14_data_i; +wire [dw-1:0] m1s14_data_o; +wire [aw-1:0] m1s14_addr; +wire [sw-1:0] m1s14_sel; +wire m1s14_we; +wire m1s14_cyc; +wire m1s14_stb; +wire m1s14_ack; +wire m1s14_err; +wire m1s14_rty; +wire [dw-1:0] m1s15_data_i; +wire [dw-1:0] m1s15_data_o; +wire [aw-1:0] m1s15_addr; +wire [sw-1:0] m1s15_sel; +wire m1s15_we; +wire m1s15_cyc; +wire m1s15_stb; +wire m1s15_ack; +wire m1s15_err; +wire m1s15_rty; +wire [dw-1:0] m2s0_data_i; +wire [dw-1:0] m2s0_data_o; +wire [aw-1:0] m2s0_addr; +wire [sw-1:0] m2s0_sel; +wire m2s0_we; +wire m2s0_cyc; +wire m2s0_stb; +wire m2s0_ack; +wire m2s0_err; +wire m2s0_rty; +wire [dw-1:0] m2s1_data_i; +wire [dw-1:0] m2s1_data_o; +wire [aw-1:0] m2s1_addr; +wire [sw-1:0] m2s1_sel; +wire m2s1_we; +wire m2s1_cyc; +wire m2s1_stb; +wire m2s1_ack; +wire m2s1_err; +wire m2s1_rty; +wire [dw-1:0] m2s2_data_i; +wire [dw-1:0] m2s2_data_o; +wire [aw-1:0] m2s2_addr; +wire [sw-1:0] m2s2_sel; +wire m2s2_we; +wire m2s2_cyc; +wire m2s2_stb; +wire m2s2_ack; +wire m2s2_err; +wire m2s2_rty; +wire [dw-1:0] m2s3_data_i; +wire [dw-1:0] m2s3_data_o; +wire [aw-1:0] m2s3_addr; +wire [sw-1:0] m2s3_sel; +wire m2s3_we; +wire m2s3_cyc; +wire m2s3_stb; +wire m2s3_ack; +wire m2s3_err; +wire m2s3_rty; +wire [dw-1:0] m2s4_data_i; +wire [dw-1:0] m2s4_data_o; +wire [aw-1:0] m2s4_addr; +wire [sw-1:0] m2s4_sel; +wire m2s4_we; +wire m2s4_cyc; +wire m2s4_stb; +wire m2s4_ack; +wire m2s4_err; +wire m2s4_rty; +wire [dw-1:0] m2s5_data_i; +wire [dw-1:0] m2s5_data_o; +wire [aw-1:0] m2s5_addr; +wire [sw-1:0] m2s5_sel; +wire m2s5_we; +wire m2s5_cyc; +wire m2s5_stb; +wire m2s5_ack; +wire m2s5_err; +wire m2s5_rty; +wire [dw-1:0] m2s6_data_i; +wire [dw-1:0] m2s6_data_o; +wire [aw-1:0] m2s6_addr; +wire [sw-1:0] m2s6_sel; +wire m2s6_we; +wire m2s6_cyc; +wire m2s6_stb; +wire m2s6_ack; +wire m2s6_err; +wire m2s6_rty; +wire [dw-1:0] m2s7_data_i; +wire [dw-1:0] m2s7_data_o; +wire [aw-1:0] m2s7_addr; +wire [sw-1:0] m2s7_sel; +wire m2s7_we; +wire m2s7_cyc; +wire m2s7_stb; +wire m2s7_ack; +wire m2s7_err; +wire m2s7_rty; +wire [dw-1:0] m2s8_data_i; +wire [dw-1:0] m2s8_data_o; +wire [aw-1:0] m2s8_addr; +wire [sw-1:0] m2s8_sel; +wire m2s8_we; +wire m2s8_cyc; +wire m2s8_stb; +wire m2s8_ack; +wire m2s8_err; +wire m2s8_rty; +wire [dw-1:0] m2s9_data_i; +wire [dw-1:0] m2s9_data_o; +wire [aw-1:0] m2s9_addr; +wire [sw-1:0] m2s9_sel; +wire m2s9_we; +wire m2s9_cyc; +wire m2s9_stb; +wire m2s9_ack; +wire m2s9_err; +wire m2s9_rty; +wire [dw-1:0] m2s10_data_i; +wire [dw-1:0] m2s10_data_o; +wire [aw-1:0] m2s10_addr; +wire [sw-1:0] m2s10_sel; +wire m2s10_we; +wire m2s10_cyc; +wire m2s10_stb; +wire m2s10_ack; +wire m2s10_err; +wire m2s10_rty; +wire [dw-1:0] m2s11_data_i; +wire [dw-1:0] m2s11_data_o; +wire [aw-1:0] m2s11_addr; +wire [sw-1:0] m2s11_sel; +wire m2s11_we; +wire m2s11_cyc; +wire m2s11_stb; +wire m2s11_ack; +wire m2s11_err; +wire m2s11_rty; +wire [dw-1:0] m2s12_data_i; +wire [dw-1:0] m2s12_data_o; +wire [aw-1:0] m2s12_addr; +wire [sw-1:0] m2s12_sel; +wire m2s12_we; +wire m2s12_cyc; +wire m2s12_stb; +wire m2s12_ack; +wire m2s12_err; +wire m2s12_rty; +wire [dw-1:0] m2s13_data_i; +wire [dw-1:0] m2s13_data_o; +wire [aw-1:0] m2s13_addr; +wire [sw-1:0] m2s13_sel; +wire m2s13_we; +wire m2s13_cyc; +wire m2s13_stb; +wire m2s13_ack; +wire m2s13_err; +wire m2s13_rty; +wire [dw-1:0] m2s14_data_i; +wire [dw-1:0] m2s14_data_o; +wire [aw-1:0] m2s14_addr; +wire [sw-1:0] m2s14_sel; +wire m2s14_we; +wire m2s14_cyc; +wire m2s14_stb; +wire m2s14_ack; +wire m2s14_err; +wire m2s14_rty; +wire [dw-1:0] m2s15_data_i; +wire [dw-1:0] m2s15_data_o; +wire [aw-1:0] m2s15_addr; +wire [sw-1:0] m2s15_sel; +wire m2s15_we; +wire m2s15_cyc; +wire m2s15_stb; +wire m2s15_ack; +wire m2s15_err; +wire m2s15_rty; +wire [dw-1:0] m3s0_data_i; +wire [dw-1:0] m3s0_data_o; +wire [aw-1:0] m3s0_addr; +wire [sw-1:0] m3s0_sel; +wire m3s0_we; +wire m3s0_cyc; +wire m3s0_stb; +wire m3s0_ack; +wire m3s0_err; +wire m3s0_rty; +wire [dw-1:0] m3s1_data_i; +wire [dw-1:0] m3s1_data_o; +wire [aw-1:0] m3s1_addr; +wire [sw-1:0] m3s1_sel; +wire m3s1_we; +wire m3s1_cyc; +wire m3s1_stb; +wire m3s1_ack; +wire m3s1_err; +wire m3s1_rty; +wire [dw-1:0] m3s2_data_i; +wire [dw-1:0] m3s2_data_o; +wire [aw-1:0] m3s2_addr; +wire [sw-1:0] m3s2_sel; +wire m3s2_we; +wire m3s2_cyc; +wire m3s2_stb; +wire m3s2_ack; +wire m3s2_err; +wire m3s2_rty; +wire [dw-1:0] m3s3_data_i; +wire [dw-1:0] m3s3_data_o; +wire [aw-1:0] m3s3_addr; +wire [sw-1:0] m3s3_sel; +wire m3s3_we; +wire m3s3_cyc; +wire m3s3_stb; +wire m3s3_ack; +wire m3s3_err; +wire m3s3_rty; +wire [dw-1:0] m3s4_data_i; +wire [dw-1:0] m3s4_data_o; +wire [aw-1:0] m3s4_addr; +wire [sw-1:0] m3s4_sel; +wire m3s4_we; +wire m3s4_cyc; +wire m3s4_stb; +wire m3s4_ack; +wire m3s4_err; +wire m3s4_rty; +wire [dw-1:0] m3s5_data_i; +wire [dw-1:0] m3s5_data_o; +wire [aw-1:0] m3s5_addr; +wire [sw-1:0] m3s5_sel; +wire m3s5_we; +wire m3s5_cyc; +wire m3s5_stb; +wire m3s5_ack; +wire m3s5_err; +wire m3s5_rty; +wire [dw-1:0] m3s6_data_i; +wire [dw-1:0] m3s6_data_o; +wire [aw-1:0] m3s6_addr; +wire [sw-1:0] m3s6_sel; +wire m3s6_we; +wire m3s6_cyc; +wire m3s6_stb; +wire m3s6_ack; +wire m3s6_err; +wire m3s6_rty; +wire [dw-1:0] m3s7_data_i; +wire [dw-1:0] m3s7_data_o; +wire [aw-1:0] m3s7_addr; +wire [sw-1:0] m3s7_sel; +wire m3s7_we; +wire m3s7_cyc; +wire m3s7_stb; +wire m3s7_ack; +wire m3s7_err; +wire m3s7_rty; +wire [dw-1:0] m3s8_data_i; +wire [dw-1:0] m3s8_data_o; +wire [aw-1:0] m3s8_addr; +wire [sw-1:0] m3s8_sel; +wire m3s8_we; +wire m3s8_cyc; +wire m3s8_stb; +wire m3s8_ack; +wire m3s8_err; +wire m3s8_rty; +wire [dw-1:0] m3s9_data_i; +wire [dw-1:0] m3s9_data_o; +wire [aw-1:0] m3s9_addr; +wire [sw-1:0] m3s9_sel; +wire m3s9_we; +wire m3s9_cyc; +wire m3s9_stb; +wire m3s9_ack; +wire m3s9_err; +wire m3s9_rty; +wire [dw-1:0] m3s10_data_i; +wire [dw-1:0] m3s10_data_o; +wire [aw-1:0] m3s10_addr; +wire [sw-1:0] m3s10_sel; +wire m3s10_we; +wire m3s10_cyc; +wire m3s10_stb; +wire m3s10_ack; +wire m3s10_err; +wire m3s10_rty; +wire [dw-1:0] m3s11_data_i; +wire [dw-1:0] m3s11_data_o; +wire [aw-1:0] m3s11_addr; +wire [sw-1:0] m3s11_sel; +wire m3s11_we; +wire m3s11_cyc; +wire m3s11_stb; +wire m3s11_ack; +wire m3s11_err; +wire m3s11_rty; +wire [dw-1:0] m3s12_data_i; +wire [dw-1:0] m3s12_data_o; +wire [aw-1:0] m3s12_addr; +wire [sw-1:0] m3s12_sel; +wire m3s12_we; +wire m3s12_cyc; +wire m3s12_stb; +wire m3s12_ack; +wire m3s12_err; +wire m3s12_rty; +wire [dw-1:0] m3s13_data_i; +wire [dw-1:0] m3s13_data_o; +wire [aw-1:0] m3s13_addr; +wire [sw-1:0] m3s13_sel; +wire m3s13_we; +wire m3s13_cyc; +wire m3s13_stb; +wire m3s13_ack; +wire m3s13_err; +wire m3s13_rty; +wire [dw-1:0] m3s14_data_i; +wire [dw-1:0] m3s14_data_o; +wire [aw-1:0] m3s14_addr; +wire [sw-1:0] m3s14_sel; +wire m3s14_we; +wire m3s14_cyc; +wire m3s14_stb; +wire m3s14_ack; +wire m3s14_err; +wire m3s14_rty; +wire [dw-1:0] m3s15_data_i; +wire [dw-1:0] m3s15_data_o; +wire [aw-1:0] m3s15_addr; +wire [sw-1:0] m3s15_sel; +wire m3s15_we; +wire m3s15_cyc; +wire m3s15_stb; +wire m3s15_ack; +wire m3s15_err; +wire m3s15_rty; +wire [dw-1:0] m4s0_data_i; +wire [dw-1:0] m4s0_data_o; +wire [aw-1:0] m4s0_addr; +wire [sw-1:0] m4s0_sel; +wire m4s0_we; +wire m4s0_cyc; +wire m4s0_stb; +wire m4s0_ack; +wire m4s0_err; +wire m4s0_rty; +wire [dw-1:0] m4s1_data_i; +wire [dw-1:0] m4s1_data_o; +wire [aw-1:0] m4s1_addr; +wire [sw-1:0] m4s1_sel; +wire m4s1_we; +wire m4s1_cyc; +wire m4s1_stb; +wire m4s1_ack; +wire m4s1_err; +wire m4s1_rty; +wire [dw-1:0] m4s2_data_i; +wire [dw-1:0] m4s2_data_o; +wire [aw-1:0] m4s2_addr; +wire [sw-1:0] m4s2_sel; +wire m4s2_we; +wire m4s2_cyc; +wire m4s2_stb; +wire m4s2_ack; +wire m4s2_err; +wire m4s2_rty; +wire [dw-1:0] m4s3_data_i; +wire [dw-1:0] m4s3_data_o; +wire [aw-1:0] m4s3_addr; +wire [sw-1:0] m4s3_sel; +wire m4s3_we; +wire m4s3_cyc; +wire m4s3_stb; +wire m4s3_ack; +wire m4s3_err; +wire m4s3_rty; +wire [dw-1:0] m4s4_data_i; +wire [dw-1:0] m4s4_data_o; +wire [aw-1:0] m4s4_addr; +wire [sw-1:0] m4s4_sel; +wire m4s4_we; +wire m4s4_cyc; +wire m4s4_stb; +wire m4s4_ack; +wire m4s4_err; +wire m4s4_rty; +wire [dw-1:0] m4s5_data_i; +wire [dw-1:0] m4s5_data_o; +wire [aw-1:0] m4s5_addr; +wire [sw-1:0] m4s5_sel; +wire m4s5_we; +wire m4s5_cyc; +wire m4s5_stb; +wire m4s5_ack; +wire m4s5_err; +wire m4s5_rty; +wire [dw-1:0] m4s6_data_i; +wire [dw-1:0] m4s6_data_o; +wire [aw-1:0] m4s6_addr; +wire [sw-1:0] m4s6_sel; +wire m4s6_we; +wire m4s6_cyc; +wire m4s6_stb; +wire m4s6_ack; +wire m4s6_err; +wire m4s6_rty; +wire [dw-1:0] m4s7_data_i; +wire [dw-1:0] m4s7_data_o; +wire [aw-1:0] m4s7_addr; +wire [sw-1:0] m4s7_sel; +wire m4s7_we; +wire m4s7_cyc; +wire m4s7_stb; +wire m4s7_ack; +wire m4s7_err; +wire m4s7_rty; +wire [dw-1:0] m4s8_data_i; +wire [dw-1:0] m4s8_data_o; +wire [aw-1:0] m4s8_addr; +wire [sw-1:0] m4s8_sel; +wire m4s8_we; +wire m4s8_cyc; +wire m4s8_stb; +wire m4s8_ack; +wire m4s8_err; +wire m4s8_rty; +wire [dw-1:0] m4s9_data_i; +wire [dw-1:0] m4s9_data_o; +wire [aw-1:0] m4s9_addr; +wire [sw-1:0] m4s9_sel; +wire m4s9_we; +wire m4s9_cyc; +wire m4s9_stb; +wire m4s9_ack; +wire m4s9_err; +wire m4s9_rty; +wire [dw-1:0] m4s10_data_i; +wire [dw-1:0] m4s10_data_o; +wire [aw-1:0] m4s10_addr; +wire [sw-1:0] m4s10_sel; +wire m4s10_we; +wire m4s10_cyc; +wire m4s10_stb; +wire m4s10_ack; +wire m4s10_err; +wire m4s10_rty; +wire [dw-1:0] m4s11_data_i; +wire [dw-1:0] m4s11_data_o; +wire [aw-1:0] m4s11_addr; +wire [sw-1:0] m4s11_sel; +wire m4s11_we; +wire m4s11_cyc; +wire m4s11_stb; +wire m4s11_ack; +wire m4s11_err; +wire m4s11_rty; +wire [dw-1:0] m4s12_data_i; +wire [dw-1:0] m4s12_data_o; +wire [aw-1:0] m4s12_addr; +wire [sw-1:0] m4s12_sel; +wire m4s12_we; +wire m4s12_cyc; +wire m4s12_stb; +wire m4s12_ack; +wire m4s12_err; +wire m4s12_rty; +wire [dw-1:0] m4s13_data_i; +wire [dw-1:0] m4s13_data_o; +wire [aw-1:0] m4s13_addr; +wire [sw-1:0] m4s13_sel; +wire m4s13_we; +wire m4s13_cyc; +wire m4s13_stb; +wire m4s13_ack; +wire m4s13_err; +wire m4s13_rty; +wire [dw-1:0] m4s14_data_i; +wire [dw-1:0] m4s14_data_o; +wire [aw-1:0] m4s14_addr; +wire [sw-1:0] m4s14_sel; +wire m4s14_we; +wire m4s14_cyc; +wire m4s14_stb; +wire m4s14_ack; +wire m4s14_err; +wire m4s14_rty; +wire [dw-1:0] m4s15_data_i; +wire [dw-1:0] m4s15_data_o; +wire [aw-1:0] m4s15_addr; +wire [sw-1:0] m4s15_sel; +wire m4s15_we; +wire m4s15_cyc; +wire m4s15_stb; +wire m4s15_ack; +wire m4s15_err; +wire m4s15_rty; +wire [dw-1:0] m5s0_data_i; +wire [dw-1:0] m5s0_data_o; +wire [aw-1:0] m5s0_addr; +wire [sw-1:0] m5s0_sel; +wire m5s0_we; +wire m5s0_cyc; +wire m5s0_stb; +wire m5s0_ack; +wire m5s0_err; +wire m5s0_rty; +wire [dw-1:0] m5s1_data_i; +wire [dw-1:0] m5s1_data_o; +wire [aw-1:0] m5s1_addr; +wire [sw-1:0] m5s1_sel; +wire m5s1_we; +wire m5s1_cyc; +wire m5s1_stb; +wire m5s1_ack; +wire m5s1_err; +wire m5s1_rty; +wire [dw-1:0] m5s2_data_i; +wire [dw-1:0] m5s2_data_o; +wire [aw-1:0] m5s2_addr; +wire [sw-1:0] m5s2_sel; +wire m5s2_we; +wire m5s2_cyc; +wire m5s2_stb; +wire m5s2_ack; +wire m5s2_err; +wire m5s2_rty; +wire [dw-1:0] m5s3_data_i; +wire [dw-1:0] m5s3_data_o; +wire [aw-1:0] m5s3_addr; +wire [sw-1:0] m5s3_sel; +wire m5s3_we; +wire m5s3_cyc; +wire m5s3_stb; +wire m5s3_ack; +wire m5s3_err; +wire m5s3_rty; +wire [dw-1:0] m5s4_data_i; +wire [dw-1:0] m5s4_data_o; +wire [aw-1:0] m5s4_addr; +wire [sw-1:0] m5s4_sel; +wire m5s4_we; +wire m5s4_cyc; +wire m5s4_stb; +wire m5s4_ack; +wire m5s4_err; +wire m5s4_rty; +wire [dw-1:0] m5s5_data_i; +wire [dw-1:0] m5s5_data_o; +wire [aw-1:0] m5s5_addr; +wire [sw-1:0] m5s5_sel; +wire m5s5_we; +wire m5s5_cyc; +wire m5s5_stb; +wire m5s5_ack; +wire m5s5_err; +wire m5s5_rty; +wire [dw-1:0] m5s6_data_i; +wire [dw-1:0] m5s6_data_o; +wire [aw-1:0] m5s6_addr; +wire [sw-1:0] m5s6_sel; +wire m5s6_we; +wire m5s6_cyc; +wire m5s6_stb; +wire m5s6_ack; +wire m5s6_err; +wire m5s6_rty; +wire [dw-1:0] m5s7_data_i; +wire [dw-1:0] m5s7_data_o; +wire [aw-1:0] m5s7_addr; +wire [sw-1:0] m5s7_sel; +wire m5s7_we; +wire m5s7_cyc; +wire m5s7_stb; +wire m5s7_ack; +wire m5s7_err; +wire m5s7_rty; +wire [dw-1:0] m5s8_data_i; +wire [dw-1:0] m5s8_data_o; +wire [aw-1:0] m5s8_addr; +wire [sw-1:0] m5s8_sel; +wire m5s8_we; +wire m5s8_cyc; +wire m5s8_stb; +wire m5s8_ack; +wire m5s8_err; +wire m5s8_rty; +wire [dw-1:0] m5s9_data_i; +wire [dw-1:0] m5s9_data_o; +wire [aw-1:0] m5s9_addr; +wire [sw-1:0] m5s9_sel; +wire m5s9_we; +wire m5s9_cyc; +wire m5s9_stb; +wire m5s9_ack; +wire m5s9_err; +wire m5s9_rty; +wire [dw-1:0] m5s10_data_i; +wire [dw-1:0] m5s10_data_o; +wire [aw-1:0] m5s10_addr; +wire [sw-1:0] m5s10_sel; +wire m5s10_we; +wire m5s10_cyc; +wire m5s10_stb; +wire m5s10_ack; +wire m5s10_err; +wire m5s10_rty; +wire [dw-1:0] m5s11_data_i; +wire [dw-1:0] m5s11_data_o; +wire [aw-1:0] m5s11_addr; +wire [sw-1:0] m5s11_sel; +wire m5s11_we; +wire m5s11_cyc; +wire m5s11_stb; +wire m5s11_ack; +wire m5s11_err; +wire m5s11_rty; +wire [dw-1:0] m5s12_data_i; +wire [dw-1:0] m5s12_data_o; +wire [aw-1:0] m5s12_addr; +wire [sw-1:0] m5s12_sel; +wire m5s12_we; +wire m5s12_cyc; +wire m5s12_stb; +wire m5s12_ack; +wire m5s12_err; +wire m5s12_rty; +wire [dw-1:0] m5s13_data_i; +wire [dw-1:0] m5s13_data_o; +wire [aw-1:0] m5s13_addr; +wire [sw-1:0] m5s13_sel; +wire m5s13_we; +wire m5s13_cyc; +wire m5s13_stb; +wire m5s13_ack; +wire m5s13_err; +wire m5s13_rty; +wire [dw-1:0] m5s14_data_i; +wire [dw-1:0] m5s14_data_o; +wire [aw-1:0] m5s14_addr; +wire [sw-1:0] m5s14_sel; +wire m5s14_we; +wire m5s14_cyc; +wire m5s14_stb; +wire m5s14_ack; +wire m5s14_err; +wire m5s14_rty; +wire [dw-1:0] m5s15_data_i; +wire [dw-1:0] m5s15_data_o; +wire [aw-1:0] m5s15_addr; +wire [sw-1:0] m5s15_sel; +wire m5s15_we; +wire m5s15_cyc; +wire m5s15_stb; +wire m5s15_ack; +wire m5s15_err; +wire m5s15_rty; +wire [dw-1:0] m6s0_data_i; +wire [dw-1:0] m6s0_data_o; +wire [aw-1:0] m6s0_addr; +wire [sw-1:0] m6s0_sel; +wire m6s0_we; +wire m6s0_cyc; +wire m6s0_stb; +wire m6s0_ack; +wire m6s0_err; +wire m6s0_rty; +wire [dw-1:0] m6s1_data_i; +wire [dw-1:0] m6s1_data_o; +wire [aw-1:0] m6s1_addr; +wire [sw-1:0] m6s1_sel; +wire m6s1_we; +wire m6s1_cyc; +wire m6s1_stb; +wire m6s1_ack; +wire m6s1_err; +wire m6s1_rty; +wire [dw-1:0] m6s2_data_i; +wire [dw-1:0] m6s2_data_o; +wire [aw-1:0] m6s2_addr; +wire [sw-1:0] m6s2_sel; +wire m6s2_we; +wire m6s2_cyc; +wire m6s2_stb; +wire m6s2_ack; +wire m6s2_err; +wire m6s2_rty; +wire [dw-1:0] m6s3_data_i; +wire [dw-1:0] m6s3_data_o; +wire [aw-1:0] m6s3_addr; +wire [sw-1:0] m6s3_sel; +wire m6s3_we; +wire m6s3_cyc; +wire m6s3_stb; +wire m6s3_ack; +wire m6s3_err; +wire m6s3_rty; +wire [dw-1:0] m6s4_data_i; +wire [dw-1:0] m6s4_data_o; +wire [aw-1:0] m6s4_addr; +wire [sw-1:0] m6s4_sel; +wire m6s4_we; +wire m6s4_cyc; +wire m6s4_stb; +wire m6s4_ack; +wire m6s4_err; +wire m6s4_rty; +wire [dw-1:0] m6s5_data_i; +wire [dw-1:0] m6s5_data_o; +wire [aw-1:0] m6s5_addr; +wire [sw-1:0] m6s5_sel; +wire m6s5_we; +wire m6s5_cyc; +wire m6s5_stb; +wire m6s5_ack; +wire m6s5_err; +wire m6s5_rty; +wire [dw-1:0] m6s6_data_i; +wire [dw-1:0] m6s6_data_o; +wire [aw-1:0] m6s6_addr; +wire [sw-1:0] m6s6_sel; +wire m6s6_we; +wire m6s6_cyc; +wire m6s6_stb; +wire m6s6_ack; +wire m6s6_err; +wire m6s6_rty; +wire [dw-1:0] m6s7_data_i; +wire [dw-1:0] m6s7_data_o; +wire [aw-1:0] m6s7_addr; +wire [sw-1:0] m6s7_sel; +wire m6s7_we; +wire m6s7_cyc; +wire m6s7_stb; +wire m6s7_ack; +wire m6s7_err; +wire m6s7_rty; +wire [dw-1:0] m6s8_data_i; +wire [dw-1:0] m6s8_data_o; +wire [aw-1:0] m6s8_addr; +wire [sw-1:0] m6s8_sel; +wire m6s8_we; +wire m6s8_cyc; +wire m6s8_stb; +wire m6s8_ack; +wire m6s8_err; +wire m6s8_rty; +wire [dw-1:0] m6s9_data_i; +wire [dw-1:0] m6s9_data_o; +wire [aw-1:0] m6s9_addr; +wire [sw-1:0] m6s9_sel; +wire m6s9_we; +wire m6s9_cyc; +wire m6s9_stb; +wire m6s9_ack; +wire m6s9_err; +wire m6s9_rty; +wire [dw-1:0] m6s10_data_i; +wire [dw-1:0] m6s10_data_o; +wire [aw-1:0] m6s10_addr; +wire [sw-1:0] m6s10_sel; +wire m6s10_we; +wire m6s10_cyc; +wire m6s10_stb; +wire m6s10_ack; +wire m6s10_err; +wire m6s10_rty; +wire [dw-1:0] m6s11_data_i; +wire [dw-1:0] m6s11_data_o; +wire [aw-1:0] m6s11_addr; +wire [sw-1:0] m6s11_sel; +wire m6s11_we; +wire m6s11_cyc; +wire m6s11_stb; +wire m6s11_ack; +wire m6s11_err; +wire m6s11_rty; +wire [dw-1:0] m6s12_data_i; +wire [dw-1:0] m6s12_data_o; +wire [aw-1:0] m6s12_addr; +wire [sw-1:0] m6s12_sel; +wire m6s12_we; +wire m6s12_cyc; +wire m6s12_stb; +wire m6s12_ack; +wire m6s12_err; +wire m6s12_rty; +wire [dw-1:0] m6s13_data_i; +wire [dw-1:0] m6s13_data_o; +wire [aw-1:0] m6s13_addr; +wire [sw-1:0] m6s13_sel; +wire m6s13_we; +wire m6s13_cyc; +wire m6s13_stb; +wire m6s13_ack; +wire m6s13_err; +wire m6s13_rty; +wire [dw-1:0] m6s14_data_i; +wire [dw-1:0] m6s14_data_o; +wire [aw-1:0] m6s14_addr; +wire [sw-1:0] m6s14_sel; +wire m6s14_we; +wire m6s14_cyc; +wire m6s14_stb; +wire m6s14_ack; +wire m6s14_err; +wire m6s14_rty; +wire [dw-1:0] m6s15_data_i; +wire [dw-1:0] m6s15_data_o; +wire [aw-1:0] m6s15_addr; +wire [sw-1:0] m6s15_sel; +wire m6s15_we; +wire m6s15_cyc; +wire m6s15_stb; +wire m6s15_ack; +wire m6s15_err; +wire m6s15_rty; +wire [dw-1:0] m7s0_data_i; +wire [dw-1:0] m7s0_data_o; +wire [aw-1:0] m7s0_addr; +wire [sw-1:0] m7s0_sel; +wire m7s0_we; +wire m7s0_cyc; +wire m7s0_stb; +wire m7s0_ack; +wire m7s0_err; +wire m7s0_rty; +wire [dw-1:0] m7s1_data_i; +wire [dw-1:0] m7s1_data_o; +wire [aw-1:0] m7s1_addr; +wire [sw-1:0] m7s1_sel; +wire m7s1_we; +wire m7s1_cyc; +wire m7s1_stb; +wire m7s1_ack; +wire m7s1_err; +wire m7s1_rty; +wire [dw-1:0] m7s2_data_i; +wire [dw-1:0] m7s2_data_o; +wire [aw-1:0] m7s2_addr; +wire [sw-1:0] m7s2_sel; +wire m7s2_we; +wire m7s2_cyc; +wire m7s2_stb; +wire m7s2_ack; +wire m7s2_err; +wire m7s2_rty; +wire [dw-1:0] m7s3_data_i; +wire [dw-1:0] m7s3_data_o; +wire [aw-1:0] m7s3_addr; +wire [sw-1:0] m7s3_sel; +wire m7s3_we; +wire m7s3_cyc; +wire m7s3_stb; +wire m7s3_ack; +wire m7s3_err; +wire m7s3_rty; +wire [dw-1:0] m7s4_data_i; +wire [dw-1:0] m7s4_data_o; +wire [aw-1:0] m7s4_addr; +wire [sw-1:0] m7s4_sel; +wire m7s4_we; +wire m7s4_cyc; +wire m7s4_stb; +wire m7s4_ack; +wire m7s4_err; +wire m7s4_rty; +wire [dw-1:0] m7s5_data_i; +wire [dw-1:0] m7s5_data_o; +wire [aw-1:0] m7s5_addr; +wire [sw-1:0] m7s5_sel; +wire m7s5_we; +wire m7s5_cyc; +wire m7s5_stb; +wire m7s5_ack; +wire m7s5_err; +wire m7s5_rty; +wire [dw-1:0] m7s6_data_i; +wire [dw-1:0] m7s6_data_o; +wire [aw-1:0] m7s6_addr; +wire [sw-1:0] m7s6_sel; +wire m7s6_we; +wire m7s6_cyc; +wire m7s6_stb; +wire m7s6_ack; +wire m7s6_err; +wire m7s6_rty; +wire [dw-1:0] m7s7_data_i; +wire [dw-1:0] m7s7_data_o; +wire [aw-1:0] m7s7_addr; +wire [sw-1:0] m7s7_sel; +wire m7s7_we; +wire m7s7_cyc; +wire m7s7_stb; +wire m7s7_ack; +wire m7s7_err; +wire m7s7_rty; +wire [dw-1:0] m7s8_data_i; +wire [dw-1:0] m7s8_data_o; +wire [aw-1:0] m7s8_addr; +wire [sw-1:0] m7s8_sel; +wire m7s8_we; +wire m7s8_cyc; +wire m7s8_stb; +wire m7s8_ack; +wire m7s8_err; +wire m7s8_rty; +wire [dw-1:0] m7s9_data_i; +wire [dw-1:0] m7s9_data_o; +wire [aw-1:0] m7s9_addr; +wire [sw-1:0] m7s9_sel; +wire m7s9_we; +wire m7s9_cyc; +wire m7s9_stb; +wire m7s9_ack; +wire m7s9_err; +wire m7s9_rty; +wire [dw-1:0] m7s10_data_i; +wire [dw-1:0] m7s10_data_o; +wire [aw-1:0] m7s10_addr; +wire [sw-1:0] m7s10_sel; +wire m7s10_we; +wire m7s10_cyc; +wire m7s10_stb; +wire m7s10_ack; +wire m7s10_err; +wire m7s10_rty; +wire [dw-1:0] m7s11_data_i; +wire [dw-1:0] m7s11_data_o; +wire [aw-1:0] m7s11_addr; +wire [sw-1:0] m7s11_sel; +wire m7s11_we; +wire m7s11_cyc; +wire m7s11_stb; +wire m7s11_ack; +wire m7s11_err; +wire m7s11_rty; +wire [dw-1:0] m7s12_data_i; +wire [dw-1:0] m7s12_data_o; +wire [aw-1:0] m7s12_addr; +wire [sw-1:0] m7s12_sel; +wire m7s12_we; +wire m7s12_cyc; +wire m7s12_stb; +wire m7s12_ack; +wire m7s12_err; +wire m7s12_rty; +wire [dw-1:0] m7s13_data_i; +wire [dw-1:0] m7s13_data_o; +wire [aw-1:0] m7s13_addr; +wire [sw-1:0] m7s13_sel; +wire m7s13_we; +wire m7s13_cyc; +wire m7s13_stb; +wire m7s13_ack; +wire m7s13_err; +wire m7s13_rty; +wire [dw-1:0] m7s14_data_i; +wire [dw-1:0] m7s14_data_o; +wire [aw-1:0] m7s14_addr; +wire [sw-1:0] m7s14_sel; +wire m7s14_we; +wire m7s14_cyc; +wire m7s14_stb; +wire m7s14_ack; +wire m7s14_err; +wire m7s14_rty; +wire [dw-1:0] m7s15_data_i; +wire [dw-1:0] m7s15_data_o; +wire [aw-1:0] m7s15_addr; +wire [sw-1:0] m7s15_sel; +wire m7s15_we; +wire m7s15_cyc; +wire m7s15_stb; +wire m7s15_ack; +wire m7s15_err; +wire m7s15_rty; + +wire [15:0] conf0; +wire [15:0] conf1; +wire [15:0] conf2; +wire [15:0] conf3; +wire [15:0] conf4; +wire [15:0] conf5; +wire [15:0] conf6; +wire [15:0] conf7; +wire [15:0] conf8; +wire [15:0] conf9; +wire [15:0] conf10; +wire [15:0] conf11; +wire [15:0] conf12; +wire [15:0] conf13; +wire [15:0] conf14; +wire [15:0] conf15; + +//////////////////////////////////////////////////////////////////// +// +// Initial Configuration Check +// + +// synopsys translate_off +initial + begin + if(dw<16) + begin + $display("ERROR: Setting Data bus width to less than 16 bits, will"); + $display(" make it impossible to use the configurations registers."); + $finish; + end + end +// synopsys translate_on + +//////////////////////////////////////////////////////////////////// +// +// Master Interfaces +// + +wb_conmax_master_if #(dw,aw,sw) m0( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m0_data_i ), + .wb_data_o( m0_data_o ), + .wb_addr_i( m0_addr_i ), + .wb_sel_i( m0_sel_i ), + .wb_we_i( m0_we_i ), + .wb_cyc_i( m0_cyc_i ), + .wb_stb_i( m0_stb_i ), + .wb_ack_o( m0_ack_o ), + .wb_err_o( m0_err_o ), + .wb_rty_o( m0_rty_o ), + .s0_data_i( m0s0_data_i ), + .s0_data_o( m0s0_data_o ), + .s0_addr_o( m0s0_addr ), + .s0_sel_o( m0s0_sel ), + .s0_we_o( m0s0_we ), + .s0_cyc_o( m0s0_cyc ), + .s0_stb_o( m0s0_stb ), + .s0_ack_i( m0s0_ack ), + .s0_err_i( m0s0_err ), + .s0_rty_i( m0s0_rty ), + .s1_data_i( m0s1_data_i ), + .s1_data_o( m0s1_data_o ), + .s1_addr_o( m0s1_addr ), + .s1_sel_o( m0s1_sel ), + .s1_we_o( m0s1_we ), + .s1_cyc_o( m0s1_cyc ), + .s1_stb_o( m0s1_stb ), + .s1_ack_i( m0s1_ack ), + .s1_err_i( m0s1_err ), + .s1_rty_i( m0s1_rty ), + .s2_data_i( m0s2_data_i ), + .s2_data_o( m0s2_data_o ), + .s2_addr_o( m0s2_addr ), + .s2_sel_o( m0s2_sel ), + .s2_we_o( m0s2_we ), + .s2_cyc_o( m0s2_cyc ), + .s2_stb_o( m0s2_stb ), + .s2_ack_i( m0s2_ack ), + .s2_err_i( m0s2_err ), + .s2_rty_i( m0s2_rty ), + .s3_data_i( m0s3_data_i ), + .s3_data_o( m0s3_data_o ), + .s3_addr_o( m0s3_addr ), + .s3_sel_o( m0s3_sel ), + .s3_we_o( m0s3_we ), + .s3_cyc_o( m0s3_cyc ), + .s3_stb_o( m0s3_stb ), + .s3_ack_i( m0s3_ack ), + .s3_err_i( m0s3_err ), + .s3_rty_i( m0s3_rty ), + .s4_data_i( m0s4_data_i ), + .s4_data_o( m0s4_data_o ), + .s4_addr_o( m0s4_addr ), + .s4_sel_o( m0s4_sel ), + .s4_we_o( m0s4_we ), + .s4_cyc_o( m0s4_cyc ), + .s4_stb_o( m0s4_stb ), + .s4_ack_i( m0s4_ack ), + .s4_err_i( m0s4_err ), + .s4_rty_i( m0s4_rty ), + .s5_data_i( m0s5_data_i ), + .s5_data_o( m0s5_data_o ), + .s5_addr_o( m0s5_addr ), + .s5_sel_o( m0s5_sel ), + .s5_we_o( m0s5_we ), + .s5_cyc_o( m0s5_cyc ), + .s5_stb_o( m0s5_stb ), + .s5_ack_i( m0s5_ack ), + .s5_err_i( m0s5_err ), + .s5_rty_i( m0s5_rty ), + .s6_data_i( m0s6_data_i ), + .s6_data_o( m0s6_data_o ), + .s6_addr_o( m0s6_addr ), + .s6_sel_o( m0s6_sel ), + .s6_we_o( m0s6_we ), + .s6_cyc_o( m0s6_cyc ), + .s6_stb_o( m0s6_stb ), + .s6_ack_i( m0s6_ack ), + .s6_err_i( m0s6_err ), + .s6_rty_i( m0s6_rty ), + .s7_data_i( m0s7_data_i ), + .s7_data_o( m0s7_data_o ), + .s7_addr_o( m0s7_addr ), + .s7_sel_o( m0s7_sel ), + .s7_we_o( m0s7_we ), + .s7_cyc_o( m0s7_cyc ), + .s7_stb_o( m0s7_stb ), + .s7_ack_i( m0s7_ack ), + .s7_err_i( m0s7_err ), + .s7_rty_i( m0s7_rty ), + .s8_data_i( m0s8_data_i ), + .s8_data_o( m0s8_data_o ), + .s8_addr_o( m0s8_addr ), + .s8_sel_o( m0s8_sel ), + .s8_we_o( m0s8_we ), + .s8_cyc_o( m0s8_cyc ), + .s8_stb_o( m0s8_stb ), + .s8_ack_i( m0s8_ack ), + .s8_err_i( m0s8_err ), + .s8_rty_i( m0s8_rty ), + .s9_data_i( m0s9_data_i ), + .s9_data_o( m0s9_data_o ), + .s9_addr_o( m0s9_addr ), + .s9_sel_o( m0s9_sel ), + .s9_we_o( m0s9_we ), + .s9_cyc_o( m0s9_cyc ), + .s9_stb_o( m0s9_stb ), + .s9_ack_i( m0s9_ack ), + .s9_err_i( m0s9_err ), + .s9_rty_i( m0s9_rty ), + .s10_data_i( m0s10_data_i ), + .s10_data_o( m0s10_data_o ), + .s10_addr_o( m0s10_addr ), + .s10_sel_o( m0s10_sel ), + .s10_we_o( m0s10_we ), + .s10_cyc_o( m0s10_cyc ), + .s10_stb_o( m0s10_stb ), + .s10_ack_i( m0s10_ack ), + .s10_err_i( m0s10_err ), + .s10_rty_i( m0s10_rty ), + .s11_data_i( m0s11_data_i ), + .s11_data_o( m0s11_data_o ), + .s11_addr_o( m0s11_addr ), + .s11_sel_o( m0s11_sel ), + .s11_we_o( m0s11_we ), + .s11_cyc_o( m0s11_cyc ), + .s11_stb_o( m0s11_stb ), + .s11_ack_i( m0s11_ack ), + .s11_err_i( m0s11_err ), + .s11_rty_i( m0s11_rty ), + .s12_data_i( m0s12_data_i ), + .s12_data_o( m0s12_data_o ), + .s12_addr_o( m0s12_addr ), + .s12_sel_o( m0s12_sel ), + .s12_we_o( m0s12_we ), + .s12_cyc_o( m0s12_cyc ), + .s12_stb_o( m0s12_stb ), + .s12_ack_i( m0s12_ack ), + .s12_err_i( m0s12_err ), + .s12_rty_i( m0s12_rty ), + .s13_data_i( m0s13_data_i ), + .s13_data_o( m0s13_data_o ), + .s13_addr_o( m0s13_addr ), + .s13_sel_o( m0s13_sel ), + .s13_we_o( m0s13_we ), + .s13_cyc_o( m0s13_cyc ), + .s13_stb_o( m0s13_stb ), + .s13_ack_i( m0s13_ack ), + .s13_err_i( m0s13_err ), + .s13_rty_i( m0s13_rty ), + .s14_data_i( m0s14_data_i ), + .s14_data_o( m0s14_data_o ), + .s14_addr_o( m0s14_addr ), + .s14_sel_o( m0s14_sel ), + .s14_we_o( m0s14_we ), + .s14_cyc_o( m0s14_cyc ), + .s14_stb_o( m0s14_stb ), + .s14_ack_i( m0s14_ack ), + .s14_err_i( m0s14_err ), + .s14_rty_i( m0s14_rty ), + .s15_data_i( m0s15_data_i ), + .s15_data_o( m0s15_data_o ), + .s15_addr_o( m0s15_addr ), + .s15_sel_o( m0s15_sel ), + .s15_we_o( m0s15_we ), + .s15_cyc_o( m0s15_cyc ), + .s15_stb_o( m0s15_stb ), + .s15_ack_i( m0s15_ack ), + .s15_err_i( m0s15_err ), + .s15_rty_i( m0s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m1( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m1_data_i ), + .wb_data_o( m1_data_o ), + .wb_addr_i( m1_addr_i ), + .wb_sel_i( m1_sel_i ), + .wb_we_i( m1_we_i ), + .wb_cyc_i( m1_cyc_i ), + .wb_stb_i( m1_stb_i ), + .wb_ack_o( m1_ack_o ), + .wb_err_o( m1_err_o ), + .wb_rty_o( m1_rty_o ), + .s0_data_i( m1s0_data_i ), + .s0_data_o( m1s0_data_o ), + .s0_addr_o( m1s0_addr ), + .s0_sel_o( m1s0_sel ), + .s0_we_o( m1s0_we ), + .s0_cyc_o( m1s0_cyc ), + .s0_stb_o( m1s0_stb ), + .s0_ack_i( m1s0_ack ), + .s0_err_i( m1s0_err ), + .s0_rty_i( m1s0_rty ), + .s1_data_i( m1s1_data_i ), + .s1_data_o( m1s1_data_o ), + .s1_addr_o( m1s1_addr ), + .s1_sel_o( m1s1_sel ), + .s1_we_o( m1s1_we ), + .s1_cyc_o( m1s1_cyc ), + .s1_stb_o( m1s1_stb ), + .s1_ack_i( m1s1_ack ), + .s1_err_i( m1s1_err ), + .s1_rty_i( m1s1_rty ), + .s2_data_i( m1s2_data_i ), + .s2_data_o( m1s2_data_o ), + .s2_addr_o( m1s2_addr ), + .s2_sel_o( m1s2_sel ), + .s2_we_o( m1s2_we ), + .s2_cyc_o( m1s2_cyc ), + .s2_stb_o( m1s2_stb ), + .s2_ack_i( m1s2_ack ), + .s2_err_i( m1s2_err ), + .s2_rty_i( m1s2_rty ), + .s3_data_i( m1s3_data_i ), + .s3_data_o( m1s3_data_o ), + .s3_addr_o( m1s3_addr ), + .s3_sel_o( m1s3_sel ), + .s3_we_o( m1s3_we ), + .s3_cyc_o( m1s3_cyc ), + .s3_stb_o( m1s3_stb ), + .s3_ack_i( m1s3_ack ), + .s3_err_i( m1s3_err ), + .s3_rty_i( m1s3_rty ), + .s4_data_i( m1s4_data_i ), + .s4_data_o( m1s4_data_o ), + .s4_addr_o( m1s4_addr ), + .s4_sel_o( m1s4_sel ), + .s4_we_o( m1s4_we ), + .s4_cyc_o( m1s4_cyc ), + .s4_stb_o( m1s4_stb ), + .s4_ack_i( m1s4_ack ), + .s4_err_i( m1s4_err ), + .s4_rty_i( m1s4_rty ), + .s5_data_i( m1s5_data_i ), + .s5_data_o( m1s5_data_o ), + .s5_addr_o( m1s5_addr ), + .s5_sel_o( m1s5_sel ), + .s5_we_o( m1s5_we ), + .s5_cyc_o( m1s5_cyc ), + .s5_stb_o( m1s5_stb ), + .s5_ack_i( m1s5_ack ), + .s5_err_i( m1s5_err ), + .s5_rty_i( m1s5_rty ), + .s6_data_i( m1s6_data_i ), + .s6_data_o( m1s6_data_o ), + .s6_addr_o( m1s6_addr ), + .s6_sel_o( m1s6_sel ), + .s6_we_o( m1s6_we ), + .s6_cyc_o( m1s6_cyc ), + .s6_stb_o( m1s6_stb ), + .s6_ack_i( m1s6_ack ), + .s6_err_i( m1s6_err ), + .s6_rty_i( m1s6_rty ), + .s7_data_i( m1s7_data_i ), + .s7_data_o( m1s7_data_o ), + .s7_addr_o( m1s7_addr ), + .s7_sel_o( m1s7_sel ), + .s7_we_o( m1s7_we ), + .s7_cyc_o( m1s7_cyc ), + .s7_stb_o( m1s7_stb ), + .s7_ack_i( m1s7_ack ), + .s7_err_i( m1s7_err ), + .s7_rty_i( m1s7_rty ), + .s8_data_i( m1s8_data_i ), + .s8_data_o( m1s8_data_o ), + .s8_addr_o( m1s8_addr ), + .s8_sel_o( m1s8_sel ), + .s8_we_o( m1s8_we ), + .s8_cyc_o( m1s8_cyc ), + .s8_stb_o( m1s8_stb ), + .s8_ack_i( m1s8_ack ), + .s8_err_i( m1s8_err ), + .s8_rty_i( m1s8_rty ), + .s9_data_i( m1s9_data_i ), + .s9_data_o( m1s9_data_o ), + .s9_addr_o( m1s9_addr ), + .s9_sel_o( m1s9_sel ), + .s9_we_o( m1s9_we ), + .s9_cyc_o( m1s9_cyc ), + .s9_stb_o( m1s9_stb ), + .s9_ack_i( m1s9_ack ), + .s9_err_i( m1s9_err ), + .s9_rty_i( m1s9_rty ), + .s10_data_i( m1s10_data_i ), + .s10_data_o( m1s10_data_o ), + .s10_addr_o( m1s10_addr ), + .s10_sel_o( m1s10_sel ), + .s10_we_o( m1s10_we ), + .s10_cyc_o( m1s10_cyc ), + .s10_stb_o( m1s10_stb ), + .s10_ack_i( m1s10_ack ), + .s10_err_i( m1s10_err ), + .s10_rty_i( m1s10_rty ), + .s11_data_i( m1s11_data_i ), + .s11_data_o( m1s11_data_o ), + .s11_addr_o( m1s11_addr ), + .s11_sel_o( m1s11_sel ), + .s11_we_o( m1s11_we ), + .s11_cyc_o( m1s11_cyc ), + .s11_stb_o( m1s11_stb ), + .s11_ack_i( m1s11_ack ), + .s11_err_i( m1s11_err ), + .s11_rty_i( m1s11_rty ), + .s12_data_i( m1s12_data_i ), + .s12_data_o( m1s12_data_o ), + .s12_addr_o( m1s12_addr ), + .s12_sel_o( m1s12_sel ), + .s12_we_o( m1s12_we ), + .s12_cyc_o( m1s12_cyc ), + .s12_stb_o( m1s12_stb ), + .s12_ack_i( m1s12_ack ), + .s12_err_i( m1s12_err ), + .s12_rty_i( m1s12_rty ), + .s13_data_i( m1s13_data_i ), + .s13_data_o( m1s13_data_o ), + .s13_addr_o( m1s13_addr ), + .s13_sel_o( m1s13_sel ), + .s13_we_o( m1s13_we ), + .s13_cyc_o( m1s13_cyc ), + .s13_stb_o( m1s13_stb ), + .s13_ack_i( m1s13_ack ), + .s13_err_i( m1s13_err ), + .s13_rty_i( m1s13_rty ), + .s14_data_i( m1s14_data_i ), + .s14_data_o( m1s14_data_o ), + .s14_addr_o( m1s14_addr ), + .s14_sel_o( m1s14_sel ), + .s14_we_o( m1s14_we ), + .s14_cyc_o( m1s14_cyc ), + .s14_stb_o( m1s14_stb ), + .s14_ack_i( m1s14_ack ), + .s14_err_i( m1s14_err ), + .s14_rty_i( m1s14_rty ), + .s15_data_i( m1s15_data_i ), + .s15_data_o( m1s15_data_o ), + .s15_addr_o( m1s15_addr ), + .s15_sel_o( m1s15_sel ), + .s15_we_o( m1s15_we ), + .s15_cyc_o( m1s15_cyc ), + .s15_stb_o( m1s15_stb ), + .s15_ack_i( m1s15_ack ), + .s15_err_i( m1s15_err ), + .s15_rty_i( m1s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m2( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m2_data_i ), + .wb_data_o( m2_data_o ), + .wb_addr_i( m2_addr_i ), + .wb_sel_i( m2_sel_i ), + .wb_we_i( m2_we_i ), + .wb_cyc_i( m2_cyc_i ), + .wb_stb_i( m2_stb_i ), + .wb_ack_o( m2_ack_o ), + .wb_err_o( m2_err_o ), + .wb_rty_o( m2_rty_o ), + .s0_data_i( m2s0_data_i ), + .s0_data_o( m2s0_data_o ), + .s0_addr_o( m2s0_addr ), + .s0_sel_o( m2s0_sel ), + .s0_we_o( m2s0_we ), + .s0_cyc_o( m2s0_cyc ), + .s0_stb_o( m2s0_stb ), + .s0_ack_i( m2s0_ack ), + .s0_err_i( m2s0_err ), + .s0_rty_i( m2s0_rty ), + .s1_data_i( m2s1_data_i ), + .s1_data_o( m2s1_data_o ), + .s1_addr_o( m2s1_addr ), + .s1_sel_o( m2s1_sel ), + .s1_we_o( m2s1_we ), + .s1_cyc_o( m2s1_cyc ), + .s1_stb_o( m2s1_stb ), + .s1_ack_i( m2s1_ack ), + .s1_err_i( m2s1_err ), + .s1_rty_i( m2s1_rty ), + .s2_data_i( m2s2_data_i ), + .s2_data_o( m2s2_data_o ), + .s2_addr_o( m2s2_addr ), + .s2_sel_o( m2s2_sel ), + .s2_we_o( m2s2_we ), + .s2_cyc_o( m2s2_cyc ), + .s2_stb_o( m2s2_stb ), + .s2_ack_i( m2s2_ack ), + .s2_err_i( m2s2_err ), + .s2_rty_i( m2s2_rty ), + .s3_data_i( m2s3_data_i ), + .s3_data_o( m2s3_data_o ), + .s3_addr_o( m2s3_addr ), + .s3_sel_o( m2s3_sel ), + .s3_we_o( m2s3_we ), + .s3_cyc_o( m2s3_cyc ), + .s3_stb_o( m2s3_stb ), + .s3_ack_i( m2s3_ack ), + .s3_err_i( m2s3_err ), + .s3_rty_i( m2s3_rty ), + .s4_data_i( m2s4_data_i ), + .s4_data_o( m2s4_data_o ), + .s4_addr_o( m2s4_addr ), + .s4_sel_o( m2s4_sel ), + .s4_we_o( m2s4_we ), + .s4_cyc_o( m2s4_cyc ), + .s4_stb_o( m2s4_stb ), + .s4_ack_i( m2s4_ack ), + .s4_err_i( m2s4_err ), + .s4_rty_i( m2s4_rty ), + .s5_data_i( m2s5_data_i ), + .s5_data_o( m2s5_data_o ), + .s5_addr_o( m2s5_addr ), + .s5_sel_o( m2s5_sel ), + .s5_we_o( m2s5_we ), + .s5_cyc_o( m2s5_cyc ), + .s5_stb_o( m2s5_stb ), + .s5_ack_i( m2s5_ack ), + .s5_err_i( m2s5_err ), + .s5_rty_i( m2s5_rty ), + .s6_data_i( m2s6_data_i ), + .s6_data_o( m2s6_data_o ), + .s6_addr_o( m2s6_addr ), + .s6_sel_o( m2s6_sel ), + .s6_we_o( m2s6_we ), + .s6_cyc_o( m2s6_cyc ), + .s6_stb_o( m2s6_stb ), + .s6_ack_i( m2s6_ack ), + .s6_err_i( m2s6_err ), + .s6_rty_i( m2s6_rty ), + .s7_data_i( m2s7_data_i ), + .s7_data_o( m2s7_data_o ), + .s7_addr_o( m2s7_addr ), + .s7_sel_o( m2s7_sel ), + .s7_we_o( m2s7_we ), + .s7_cyc_o( m2s7_cyc ), + .s7_stb_o( m2s7_stb ), + .s7_ack_i( m2s7_ack ), + .s7_err_i( m2s7_err ), + .s7_rty_i( m2s7_rty ), + .s8_data_i( m2s8_data_i ), + .s8_data_o( m2s8_data_o ), + .s8_addr_o( m2s8_addr ), + .s8_sel_o( m2s8_sel ), + .s8_we_o( m2s8_we ), + .s8_cyc_o( m2s8_cyc ), + .s8_stb_o( m2s8_stb ), + .s8_ack_i( m2s8_ack ), + .s8_err_i( m2s8_err ), + .s8_rty_i( m2s8_rty ), + .s9_data_i( m2s9_data_i ), + .s9_data_o( m2s9_data_o ), + .s9_addr_o( m2s9_addr ), + .s9_sel_o( m2s9_sel ), + .s9_we_o( m2s9_we ), + .s9_cyc_o( m2s9_cyc ), + .s9_stb_o( m2s9_stb ), + .s9_ack_i( m2s9_ack ), + .s9_err_i( m2s9_err ), + .s9_rty_i( m2s9_rty ), + .s10_data_i( m2s10_data_i ), + .s10_data_o( m2s10_data_o ), + .s10_addr_o( m2s10_addr ), + .s10_sel_o( m2s10_sel ), + .s10_we_o( m2s10_we ), + .s10_cyc_o( m2s10_cyc ), + .s10_stb_o( m2s10_stb ), + .s10_ack_i( m2s10_ack ), + .s10_err_i( m2s10_err ), + .s10_rty_i( m2s10_rty ), + .s11_data_i( m2s11_data_i ), + .s11_data_o( m2s11_data_o ), + .s11_addr_o( m2s11_addr ), + .s11_sel_o( m2s11_sel ), + .s11_we_o( m2s11_we ), + .s11_cyc_o( m2s11_cyc ), + .s11_stb_o( m2s11_stb ), + .s11_ack_i( m2s11_ack ), + .s11_err_i( m2s11_err ), + .s11_rty_i( m2s11_rty ), + .s12_data_i( m2s12_data_i ), + .s12_data_o( m2s12_data_o ), + .s12_addr_o( m2s12_addr ), + .s12_sel_o( m2s12_sel ), + .s12_we_o( m2s12_we ), + .s12_cyc_o( m2s12_cyc ), + .s12_stb_o( m2s12_stb ), + .s12_ack_i( m2s12_ack ), + .s12_err_i( m2s12_err ), + .s12_rty_i( m2s12_rty ), + .s13_data_i( m2s13_data_i ), + .s13_data_o( m2s13_data_o ), + .s13_addr_o( m2s13_addr ), + .s13_sel_o( m2s13_sel ), + .s13_we_o( m2s13_we ), + .s13_cyc_o( m2s13_cyc ), + .s13_stb_o( m2s13_stb ), + .s13_ack_i( m2s13_ack ), + .s13_err_i( m2s13_err ), + .s13_rty_i( m2s13_rty ), + .s14_data_i( m2s14_data_i ), + .s14_data_o( m2s14_data_o ), + .s14_addr_o( m2s14_addr ), + .s14_sel_o( m2s14_sel ), + .s14_we_o( m2s14_we ), + .s14_cyc_o( m2s14_cyc ), + .s14_stb_o( m2s14_stb ), + .s14_ack_i( m2s14_ack ), + .s14_err_i( m2s14_err ), + .s14_rty_i( m2s14_rty ), + .s15_data_i( m2s15_data_i ), + .s15_data_o( m2s15_data_o ), + .s15_addr_o( m2s15_addr ), + .s15_sel_o( m2s15_sel ), + .s15_we_o( m2s15_we ), + .s15_cyc_o( m2s15_cyc ), + .s15_stb_o( m2s15_stb ), + .s15_ack_i( m2s15_ack ), + .s15_err_i( m2s15_err ), + .s15_rty_i( m2s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m3( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m3_data_i ), + .wb_data_o( m3_data_o ), + .wb_addr_i( m3_addr_i ), + .wb_sel_i( m3_sel_i ), + .wb_we_i( m3_we_i ), + .wb_cyc_i( m3_cyc_i ), + .wb_stb_i( m3_stb_i ), + .wb_ack_o( m3_ack_o ), + .wb_err_o( m3_err_o ), + .wb_rty_o( m3_rty_o ), + .s0_data_i( m3s0_data_i ), + .s0_data_o( m3s0_data_o ), + .s0_addr_o( m3s0_addr ), + .s0_sel_o( m3s0_sel ), + .s0_we_o( m3s0_we ), + .s0_cyc_o( m3s0_cyc ), + .s0_stb_o( m3s0_stb ), + .s0_ack_i( m3s0_ack ), + .s0_err_i( m3s0_err ), + .s0_rty_i( m3s0_rty ), + .s1_data_i( m3s1_data_i ), + .s1_data_o( m3s1_data_o ), + .s1_addr_o( m3s1_addr ), + .s1_sel_o( m3s1_sel ), + .s1_we_o( m3s1_we ), + .s1_cyc_o( m3s1_cyc ), + .s1_stb_o( m3s1_stb ), + .s1_ack_i( m3s1_ack ), + .s1_err_i( m3s1_err ), + .s1_rty_i( m3s1_rty ), + .s2_data_i( m3s2_data_i ), + .s2_data_o( m3s2_data_o ), + .s2_addr_o( m3s2_addr ), + .s2_sel_o( m3s2_sel ), + .s2_we_o( m3s2_we ), + .s2_cyc_o( m3s2_cyc ), + .s2_stb_o( m3s2_stb ), + .s2_ack_i( m3s2_ack ), + .s2_err_i( m3s2_err ), + .s2_rty_i( m3s2_rty ), + .s3_data_i( m3s3_data_i ), + .s3_data_o( m3s3_data_o ), + .s3_addr_o( m3s3_addr ), + .s3_sel_o( m3s3_sel ), + .s3_we_o( m3s3_we ), + .s3_cyc_o( m3s3_cyc ), + .s3_stb_o( m3s3_stb ), + .s3_ack_i( m3s3_ack ), + .s3_err_i( m3s3_err ), + .s3_rty_i( m3s3_rty ), + .s4_data_i( m3s4_data_i ), + .s4_data_o( m3s4_data_o ), + .s4_addr_o( m3s4_addr ), + .s4_sel_o( m3s4_sel ), + .s4_we_o( m3s4_we ), + .s4_cyc_o( m3s4_cyc ), + .s4_stb_o( m3s4_stb ), + .s4_ack_i( m3s4_ack ), + .s4_err_i( m3s4_err ), + .s4_rty_i( m3s4_rty ), + .s5_data_i( m3s5_data_i ), + .s5_data_o( m3s5_data_o ), + .s5_addr_o( m3s5_addr ), + .s5_sel_o( m3s5_sel ), + .s5_we_o( m3s5_we ), + .s5_cyc_o( m3s5_cyc ), + .s5_stb_o( m3s5_stb ), + .s5_ack_i( m3s5_ack ), + .s5_err_i( m3s5_err ), + .s5_rty_i( m3s5_rty ), + .s6_data_i( m3s6_data_i ), + .s6_data_o( m3s6_data_o ), + .s6_addr_o( m3s6_addr ), + .s6_sel_o( m3s6_sel ), + .s6_we_o( m3s6_we ), + .s6_cyc_o( m3s6_cyc ), + .s6_stb_o( m3s6_stb ), + .s6_ack_i( m3s6_ack ), + .s6_err_i( m3s6_err ), + .s6_rty_i( m3s6_rty ), + .s7_data_i( m3s7_data_i ), + .s7_data_o( m3s7_data_o ), + .s7_addr_o( m3s7_addr ), + .s7_sel_o( m3s7_sel ), + .s7_we_o( m3s7_we ), + .s7_cyc_o( m3s7_cyc ), + .s7_stb_o( m3s7_stb ), + .s7_ack_i( m3s7_ack ), + .s7_err_i( m3s7_err ), + .s7_rty_i( m3s7_rty ), + .s8_data_i( m3s8_data_i ), + .s8_data_o( m3s8_data_o ), + .s8_addr_o( m3s8_addr ), + .s8_sel_o( m3s8_sel ), + .s8_we_o( m3s8_we ), + .s8_cyc_o( m3s8_cyc ), + .s8_stb_o( m3s8_stb ), + .s8_ack_i( m3s8_ack ), + .s8_err_i( m3s8_err ), + .s8_rty_i( m3s8_rty ), + .s9_data_i( m3s9_data_i ), + .s9_data_o( m3s9_data_o ), + .s9_addr_o( m3s9_addr ), + .s9_sel_o( m3s9_sel ), + .s9_we_o( m3s9_we ), + .s9_cyc_o( m3s9_cyc ), + .s9_stb_o( m3s9_stb ), + .s9_ack_i( m3s9_ack ), + .s9_err_i( m3s9_err ), + .s9_rty_i( m3s9_rty ), + .s10_data_i( m3s10_data_i ), + .s10_data_o( m3s10_data_o ), + .s10_addr_o( m3s10_addr ), + .s10_sel_o( m3s10_sel ), + .s10_we_o( m3s10_we ), + .s10_cyc_o( m3s10_cyc ), + .s10_stb_o( m3s10_stb ), + .s10_ack_i( m3s10_ack ), + .s10_err_i( m3s10_err ), + .s10_rty_i( m3s10_rty ), + .s11_data_i( m3s11_data_i ), + .s11_data_o( m3s11_data_o ), + .s11_addr_o( m3s11_addr ), + .s11_sel_o( m3s11_sel ), + .s11_we_o( m3s11_we ), + .s11_cyc_o( m3s11_cyc ), + .s11_stb_o( m3s11_stb ), + .s11_ack_i( m3s11_ack ), + .s11_err_i( m3s11_err ), + .s11_rty_i( m3s11_rty ), + .s12_data_i( m3s12_data_i ), + .s12_data_o( m3s12_data_o ), + .s12_addr_o( m3s12_addr ), + .s12_sel_o( m3s12_sel ), + .s12_we_o( m3s12_we ), + .s12_cyc_o( m3s12_cyc ), + .s12_stb_o( m3s12_stb ), + .s12_ack_i( m3s12_ack ), + .s12_err_i( m3s12_err ), + .s12_rty_i( m3s12_rty ), + .s13_data_i( m3s13_data_i ), + .s13_data_o( m3s13_data_o ), + .s13_addr_o( m3s13_addr ), + .s13_sel_o( m3s13_sel ), + .s13_we_o( m3s13_we ), + .s13_cyc_o( m3s13_cyc ), + .s13_stb_o( m3s13_stb ), + .s13_ack_i( m3s13_ack ), + .s13_err_i( m3s13_err ), + .s13_rty_i( m3s13_rty ), + .s14_data_i( m3s14_data_i ), + .s14_data_o( m3s14_data_o ), + .s14_addr_o( m3s14_addr ), + .s14_sel_o( m3s14_sel ), + .s14_we_o( m3s14_we ), + .s14_cyc_o( m3s14_cyc ), + .s14_stb_o( m3s14_stb ), + .s14_ack_i( m3s14_ack ), + .s14_err_i( m3s14_err ), + .s14_rty_i( m3s14_rty ), + .s15_data_i( m3s15_data_i ), + .s15_data_o( m3s15_data_o ), + .s15_addr_o( m3s15_addr ), + .s15_sel_o( m3s15_sel ), + .s15_we_o( m3s15_we ), + .s15_cyc_o( m3s15_cyc ), + .s15_stb_o( m3s15_stb ), + .s15_ack_i( m3s15_ack ), + .s15_err_i( m3s15_err ), + .s15_rty_i( m3s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m4( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m4_data_i ), + .wb_data_o( m4_data_o ), + .wb_addr_i( m4_addr_i ), + .wb_sel_i( m4_sel_i ), + .wb_we_i( m4_we_i ), + .wb_cyc_i( m4_cyc_i ), + .wb_stb_i( m4_stb_i ), + .wb_ack_o( m4_ack_o ), + .wb_err_o( m4_err_o ), + .wb_rty_o( m4_rty_o ), + .s0_data_i( m4s0_data_i ), + .s0_data_o( m4s0_data_o ), + .s0_addr_o( m4s0_addr ), + .s0_sel_o( m4s0_sel ), + .s0_we_o( m4s0_we ), + .s0_cyc_o( m4s0_cyc ), + .s0_stb_o( m4s0_stb ), + .s0_ack_i( m4s0_ack ), + .s0_err_i( m4s0_err ), + .s0_rty_i( m4s0_rty ), + .s1_data_i( m4s1_data_i ), + .s1_data_o( m4s1_data_o ), + .s1_addr_o( m4s1_addr ), + .s1_sel_o( m4s1_sel ), + .s1_we_o( m4s1_we ), + .s1_cyc_o( m4s1_cyc ), + .s1_stb_o( m4s1_stb ), + .s1_ack_i( m4s1_ack ), + .s1_err_i( m4s1_err ), + .s1_rty_i( m4s1_rty ), + .s2_data_i( m4s2_data_i ), + .s2_data_o( m4s2_data_o ), + .s2_addr_o( m4s2_addr ), + .s2_sel_o( m4s2_sel ), + .s2_we_o( m4s2_we ), + .s2_cyc_o( m4s2_cyc ), + .s2_stb_o( m4s2_stb ), + .s2_ack_i( m4s2_ack ), + .s2_err_i( m4s2_err ), + .s2_rty_i( m4s2_rty ), + .s3_data_i( m4s3_data_i ), + .s3_data_o( m4s3_data_o ), + .s3_addr_o( m4s3_addr ), + .s3_sel_o( m4s3_sel ), + .s3_we_o( m4s3_we ), + .s3_cyc_o( m4s3_cyc ), + .s3_stb_o( m4s3_stb ), + .s3_ack_i( m4s3_ack ), + .s3_err_i( m4s3_err ), + .s3_rty_i( m4s3_rty ), + .s4_data_i( m4s4_data_i ), + .s4_data_o( m4s4_data_o ), + .s4_addr_o( m4s4_addr ), + .s4_sel_o( m4s4_sel ), + .s4_we_o( m4s4_we ), + .s4_cyc_o( m4s4_cyc ), + .s4_stb_o( m4s4_stb ), + .s4_ack_i( m4s4_ack ), + .s4_err_i( m4s4_err ), + .s4_rty_i( m4s4_rty ), + .s5_data_i( m4s5_data_i ), + .s5_data_o( m4s5_data_o ), + .s5_addr_o( m4s5_addr ), + .s5_sel_o( m4s5_sel ), + .s5_we_o( m4s5_we ), + .s5_cyc_o( m4s5_cyc ), + .s5_stb_o( m4s5_stb ), + .s5_ack_i( m4s5_ack ), + .s5_err_i( m4s5_err ), + .s5_rty_i( m4s5_rty ), + .s6_data_i( m4s6_data_i ), + .s6_data_o( m4s6_data_o ), + .s6_addr_o( m4s6_addr ), + .s6_sel_o( m4s6_sel ), + .s6_we_o( m4s6_we ), + .s6_cyc_o( m4s6_cyc ), + .s6_stb_o( m4s6_stb ), + .s6_ack_i( m4s6_ack ), + .s6_err_i( m4s6_err ), + .s6_rty_i( m4s6_rty ), + .s7_data_i( m4s7_data_i ), + .s7_data_o( m4s7_data_o ), + .s7_addr_o( m4s7_addr ), + .s7_sel_o( m4s7_sel ), + .s7_we_o( m4s7_we ), + .s7_cyc_o( m4s7_cyc ), + .s7_stb_o( m4s7_stb ), + .s7_ack_i( m4s7_ack ), + .s7_err_i( m4s7_err ), + .s7_rty_i( m4s7_rty ), + .s8_data_i( m4s8_data_i ), + .s8_data_o( m4s8_data_o ), + .s8_addr_o( m4s8_addr ), + .s8_sel_o( m4s8_sel ), + .s8_we_o( m4s8_we ), + .s8_cyc_o( m4s8_cyc ), + .s8_stb_o( m4s8_stb ), + .s8_ack_i( m4s8_ack ), + .s8_err_i( m4s8_err ), + .s8_rty_i( m4s8_rty ), + .s9_data_i( m4s9_data_i ), + .s9_data_o( m4s9_data_o ), + .s9_addr_o( m4s9_addr ), + .s9_sel_o( m4s9_sel ), + .s9_we_o( m4s9_we ), + .s9_cyc_o( m4s9_cyc ), + .s9_stb_o( m4s9_stb ), + .s9_ack_i( m4s9_ack ), + .s9_err_i( m4s9_err ), + .s9_rty_i( m4s9_rty ), + .s10_data_i( m4s10_data_i ), + .s10_data_o( m4s10_data_o ), + .s10_addr_o( m4s10_addr ), + .s10_sel_o( m4s10_sel ), + .s10_we_o( m4s10_we ), + .s10_cyc_o( m4s10_cyc ), + .s10_stb_o( m4s10_stb ), + .s10_ack_i( m4s10_ack ), + .s10_err_i( m4s10_err ), + .s10_rty_i( m4s10_rty ), + .s11_data_i( m4s11_data_i ), + .s11_data_o( m4s11_data_o ), + .s11_addr_o( m4s11_addr ), + .s11_sel_o( m4s11_sel ), + .s11_we_o( m4s11_we ), + .s11_cyc_o( m4s11_cyc ), + .s11_stb_o( m4s11_stb ), + .s11_ack_i( m4s11_ack ), + .s11_err_i( m4s11_err ), + .s11_rty_i( m4s11_rty ), + .s12_data_i( m4s12_data_i ), + .s12_data_o( m4s12_data_o ), + .s12_addr_o( m4s12_addr ), + .s12_sel_o( m4s12_sel ), + .s12_we_o( m4s12_we ), + .s12_cyc_o( m4s12_cyc ), + .s12_stb_o( m4s12_stb ), + .s12_ack_i( m4s12_ack ), + .s12_err_i( m4s12_err ), + .s12_rty_i( m4s12_rty ), + .s13_data_i( m4s13_data_i ), + .s13_data_o( m4s13_data_o ), + .s13_addr_o( m4s13_addr ), + .s13_sel_o( m4s13_sel ), + .s13_we_o( m4s13_we ), + .s13_cyc_o( m4s13_cyc ), + .s13_stb_o( m4s13_stb ), + .s13_ack_i( m4s13_ack ), + .s13_err_i( m4s13_err ), + .s13_rty_i( m4s13_rty ), + .s14_data_i( m4s14_data_i ), + .s14_data_o( m4s14_data_o ), + .s14_addr_o( m4s14_addr ), + .s14_sel_o( m4s14_sel ), + .s14_we_o( m4s14_we ), + .s14_cyc_o( m4s14_cyc ), + .s14_stb_o( m4s14_stb ), + .s14_ack_i( m4s14_ack ), + .s14_err_i( m4s14_err ), + .s14_rty_i( m4s14_rty ), + .s15_data_i( m4s15_data_i ), + .s15_data_o( m4s15_data_o ), + .s15_addr_o( m4s15_addr ), + .s15_sel_o( m4s15_sel ), + .s15_we_o( m4s15_we ), + .s15_cyc_o( m4s15_cyc ), + .s15_stb_o( m4s15_stb ), + .s15_ack_i( m4s15_ack ), + .s15_err_i( m4s15_err ), + .s15_rty_i( m4s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m5( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m5_data_i ), + .wb_data_o( m5_data_o ), + .wb_addr_i( m5_addr_i ), + .wb_sel_i( m5_sel_i ), + .wb_we_i( m5_we_i ), + .wb_cyc_i( m5_cyc_i ), + .wb_stb_i( m5_stb_i ), + .wb_ack_o( m5_ack_o ), + .wb_err_o( m5_err_o ), + .wb_rty_o( m5_rty_o ), + .s0_data_i( m5s0_data_i ), + .s0_data_o( m5s0_data_o ), + .s0_addr_o( m5s0_addr ), + .s0_sel_o( m5s0_sel ), + .s0_we_o( m5s0_we ), + .s0_cyc_o( m5s0_cyc ), + .s0_stb_o( m5s0_stb ), + .s0_ack_i( m5s0_ack ), + .s0_err_i( m5s0_err ), + .s0_rty_i( m5s0_rty ), + .s1_data_i( m5s1_data_i ), + .s1_data_o( m5s1_data_o ), + .s1_addr_o( m5s1_addr ), + .s1_sel_o( m5s1_sel ), + .s1_we_o( m5s1_we ), + .s1_cyc_o( m5s1_cyc ), + .s1_stb_o( m5s1_stb ), + .s1_ack_i( m5s1_ack ), + .s1_err_i( m5s1_err ), + .s1_rty_i( m5s1_rty ), + .s2_data_i( m5s2_data_i ), + .s2_data_o( m5s2_data_o ), + .s2_addr_o( m5s2_addr ), + .s2_sel_o( m5s2_sel ), + .s2_we_o( m5s2_we ), + .s2_cyc_o( m5s2_cyc ), + .s2_stb_o( m5s2_stb ), + .s2_ack_i( m5s2_ack ), + .s2_err_i( m5s2_err ), + .s2_rty_i( m5s2_rty ), + .s3_data_i( m5s3_data_i ), + .s3_data_o( m5s3_data_o ), + .s3_addr_o( m5s3_addr ), + .s3_sel_o( m5s3_sel ), + .s3_we_o( m5s3_we ), + .s3_cyc_o( m5s3_cyc ), + .s3_stb_o( m5s3_stb ), + .s3_ack_i( m5s3_ack ), + .s3_err_i( m5s3_err ), + .s3_rty_i( m5s3_rty ), + .s4_data_i( m5s4_data_i ), + .s4_data_o( m5s4_data_o ), + .s4_addr_o( m5s4_addr ), + .s4_sel_o( m5s4_sel ), + .s4_we_o( m5s4_we ), + .s4_cyc_o( m5s4_cyc ), + .s4_stb_o( m5s4_stb ), + .s4_ack_i( m5s4_ack ), + .s4_err_i( m5s4_err ), + .s4_rty_i( m5s4_rty ), + .s5_data_i( m5s5_data_i ), + .s5_data_o( m5s5_data_o ), + .s5_addr_o( m5s5_addr ), + .s5_sel_o( m5s5_sel ), + .s5_we_o( m5s5_we ), + .s5_cyc_o( m5s5_cyc ), + .s5_stb_o( m5s5_stb ), + .s5_ack_i( m5s5_ack ), + .s5_err_i( m5s5_err ), + .s5_rty_i( m5s5_rty ), + .s6_data_i( m5s6_data_i ), + .s6_data_o( m5s6_data_o ), + .s6_addr_o( m5s6_addr ), + .s6_sel_o( m5s6_sel ), + .s6_we_o( m5s6_we ), + .s6_cyc_o( m5s6_cyc ), + .s6_stb_o( m5s6_stb ), + .s6_ack_i( m5s6_ack ), + .s6_err_i( m5s6_err ), + .s6_rty_i( m5s6_rty ), + .s7_data_i( m5s7_data_i ), + .s7_data_o( m5s7_data_o ), + .s7_addr_o( m5s7_addr ), + .s7_sel_o( m5s7_sel ), + .s7_we_o( m5s7_we ), + .s7_cyc_o( m5s7_cyc ), + .s7_stb_o( m5s7_stb ), + .s7_ack_i( m5s7_ack ), + .s7_err_i( m5s7_err ), + .s7_rty_i( m5s7_rty ), + .s8_data_i( m5s8_data_i ), + .s8_data_o( m5s8_data_o ), + .s8_addr_o( m5s8_addr ), + .s8_sel_o( m5s8_sel ), + .s8_we_o( m5s8_we ), + .s8_cyc_o( m5s8_cyc ), + .s8_stb_o( m5s8_stb ), + .s8_ack_i( m5s8_ack ), + .s8_err_i( m5s8_err ), + .s8_rty_i( m5s8_rty ), + .s9_data_i( m5s9_data_i ), + .s9_data_o( m5s9_data_o ), + .s9_addr_o( m5s9_addr ), + .s9_sel_o( m5s9_sel ), + .s9_we_o( m5s9_we ), + .s9_cyc_o( m5s9_cyc ), + .s9_stb_o( m5s9_stb ), + .s9_ack_i( m5s9_ack ), + .s9_err_i( m5s9_err ), + .s9_rty_i( m5s9_rty ), + .s10_data_i( m5s10_data_i ), + .s10_data_o( m5s10_data_o ), + .s10_addr_o( m5s10_addr ), + .s10_sel_o( m5s10_sel ), + .s10_we_o( m5s10_we ), + .s10_cyc_o( m5s10_cyc ), + .s10_stb_o( m5s10_stb ), + .s10_ack_i( m5s10_ack ), + .s10_err_i( m5s10_err ), + .s10_rty_i( m5s10_rty ), + .s11_data_i( m5s11_data_i ), + .s11_data_o( m5s11_data_o ), + .s11_addr_o( m5s11_addr ), + .s11_sel_o( m5s11_sel ), + .s11_we_o( m5s11_we ), + .s11_cyc_o( m5s11_cyc ), + .s11_stb_o( m5s11_stb ), + .s11_ack_i( m5s11_ack ), + .s11_err_i( m5s11_err ), + .s11_rty_i( m5s11_rty ), + .s12_data_i( m5s12_data_i ), + .s12_data_o( m5s12_data_o ), + .s12_addr_o( m5s12_addr ), + .s12_sel_o( m5s12_sel ), + .s12_we_o( m5s12_we ), + .s12_cyc_o( m5s12_cyc ), + .s12_stb_o( m5s12_stb ), + .s12_ack_i( m5s12_ack ), + .s12_err_i( m5s12_err ), + .s12_rty_i( m5s12_rty ), + .s13_data_i( m5s13_data_i ), + .s13_data_o( m5s13_data_o ), + .s13_addr_o( m5s13_addr ), + .s13_sel_o( m5s13_sel ), + .s13_we_o( m5s13_we ), + .s13_cyc_o( m5s13_cyc ), + .s13_stb_o( m5s13_stb ), + .s13_ack_i( m5s13_ack ), + .s13_err_i( m5s13_err ), + .s13_rty_i( m5s13_rty ), + .s14_data_i( m5s14_data_i ), + .s14_data_o( m5s14_data_o ), + .s14_addr_o( m5s14_addr ), + .s14_sel_o( m5s14_sel ), + .s14_we_o( m5s14_we ), + .s14_cyc_o( m5s14_cyc ), + .s14_stb_o( m5s14_stb ), + .s14_ack_i( m5s14_ack ), + .s14_err_i( m5s14_err ), + .s14_rty_i( m5s14_rty ), + .s15_data_i( m5s15_data_i ), + .s15_data_o( m5s15_data_o ), + .s15_addr_o( m5s15_addr ), + .s15_sel_o( m5s15_sel ), + .s15_we_o( m5s15_we ), + .s15_cyc_o( m5s15_cyc ), + .s15_stb_o( m5s15_stb ), + .s15_ack_i( m5s15_ack ), + .s15_err_i( m5s15_err ), + .s15_rty_i( m5s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m6( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m6_data_i ), + .wb_data_o( m6_data_o ), + .wb_addr_i( m6_addr_i ), + .wb_sel_i( m6_sel_i ), + .wb_we_i( m6_we_i ), + .wb_cyc_i( m6_cyc_i ), + .wb_stb_i( m6_stb_i ), + .wb_ack_o( m6_ack_o ), + .wb_err_o( m6_err_o ), + .wb_rty_o( m6_rty_o ), + .s0_data_i( m6s0_data_i ), + .s0_data_o( m6s0_data_o ), + .s0_addr_o( m6s0_addr ), + .s0_sel_o( m6s0_sel ), + .s0_we_o( m6s0_we ), + .s0_cyc_o( m6s0_cyc ), + .s0_stb_o( m6s0_stb ), + .s0_ack_i( m6s0_ack ), + .s0_err_i( m6s0_err ), + .s0_rty_i( m6s0_rty ), + .s1_data_i( m6s1_data_i ), + .s1_data_o( m6s1_data_o ), + .s1_addr_o( m6s1_addr ), + .s1_sel_o( m6s1_sel ), + .s1_we_o( m6s1_we ), + .s1_cyc_o( m6s1_cyc ), + .s1_stb_o( m6s1_stb ), + .s1_ack_i( m6s1_ack ), + .s1_err_i( m6s1_err ), + .s1_rty_i( m6s1_rty ), + .s2_data_i( m6s2_data_i ), + .s2_data_o( m6s2_data_o ), + .s2_addr_o( m6s2_addr ), + .s2_sel_o( m6s2_sel ), + .s2_we_o( m6s2_we ), + .s2_cyc_o( m6s2_cyc ), + .s2_stb_o( m6s2_stb ), + .s2_ack_i( m6s2_ack ), + .s2_err_i( m6s2_err ), + .s2_rty_i( m6s2_rty ), + .s3_data_i( m6s3_data_i ), + .s3_data_o( m6s3_data_o ), + .s3_addr_o( m6s3_addr ), + .s3_sel_o( m6s3_sel ), + .s3_we_o( m6s3_we ), + .s3_cyc_o( m6s3_cyc ), + .s3_stb_o( m6s3_stb ), + .s3_ack_i( m6s3_ack ), + .s3_err_i( m6s3_err ), + .s3_rty_i( m6s3_rty ), + .s4_data_i( m6s4_data_i ), + .s4_data_o( m6s4_data_o ), + .s4_addr_o( m6s4_addr ), + .s4_sel_o( m6s4_sel ), + .s4_we_o( m6s4_we ), + .s4_cyc_o( m6s4_cyc ), + .s4_stb_o( m6s4_stb ), + .s4_ack_i( m6s4_ack ), + .s4_err_i( m6s4_err ), + .s4_rty_i( m6s4_rty ), + .s5_data_i( m6s5_data_i ), + .s5_data_o( m6s5_data_o ), + .s5_addr_o( m6s5_addr ), + .s5_sel_o( m6s5_sel ), + .s5_we_o( m6s5_we ), + .s5_cyc_o( m6s5_cyc ), + .s5_stb_o( m6s5_stb ), + .s5_ack_i( m6s5_ack ), + .s5_err_i( m6s5_err ), + .s5_rty_i( m6s5_rty ), + .s6_data_i( m6s6_data_i ), + .s6_data_o( m6s6_data_o ), + .s6_addr_o( m6s6_addr ), + .s6_sel_o( m6s6_sel ), + .s6_we_o( m6s6_we ), + .s6_cyc_o( m6s6_cyc ), + .s6_stb_o( m6s6_stb ), + .s6_ack_i( m6s6_ack ), + .s6_err_i( m6s6_err ), + .s6_rty_i( m6s6_rty ), + .s7_data_i( m6s7_data_i ), + .s7_data_o( m6s7_data_o ), + .s7_addr_o( m6s7_addr ), + .s7_sel_o( m6s7_sel ), + .s7_we_o( m6s7_we ), + .s7_cyc_o( m6s7_cyc ), + .s7_stb_o( m6s7_stb ), + .s7_ack_i( m6s7_ack ), + .s7_err_i( m6s7_err ), + .s7_rty_i( m6s7_rty ), + .s8_data_i( m6s8_data_i ), + .s8_data_o( m6s8_data_o ), + .s8_addr_o( m6s8_addr ), + .s8_sel_o( m6s8_sel ), + .s8_we_o( m6s8_we ), + .s8_cyc_o( m6s8_cyc ), + .s8_stb_o( m6s8_stb ), + .s8_ack_i( m6s8_ack ), + .s8_err_i( m6s8_err ), + .s8_rty_i( m6s8_rty ), + .s9_data_i( m6s9_data_i ), + .s9_data_o( m6s9_data_o ), + .s9_addr_o( m6s9_addr ), + .s9_sel_o( m6s9_sel ), + .s9_we_o( m6s9_we ), + .s9_cyc_o( m6s9_cyc ), + .s9_stb_o( m6s9_stb ), + .s9_ack_i( m6s9_ack ), + .s9_err_i( m6s9_err ), + .s9_rty_i( m6s9_rty ), + .s10_data_i( m6s10_data_i ), + .s10_data_o( m6s10_data_o ), + .s10_addr_o( m6s10_addr ), + .s10_sel_o( m6s10_sel ), + .s10_we_o( m6s10_we ), + .s10_cyc_o( m6s10_cyc ), + .s10_stb_o( m6s10_stb ), + .s10_ack_i( m6s10_ack ), + .s10_err_i( m6s10_err ), + .s10_rty_i( m6s10_rty ), + .s11_data_i( m6s11_data_i ), + .s11_data_o( m6s11_data_o ), + .s11_addr_o( m6s11_addr ), + .s11_sel_o( m6s11_sel ), + .s11_we_o( m6s11_we ), + .s11_cyc_o( m6s11_cyc ), + .s11_stb_o( m6s11_stb ), + .s11_ack_i( m6s11_ack ), + .s11_err_i( m6s11_err ), + .s11_rty_i( m6s11_rty ), + .s12_data_i( m6s12_data_i ), + .s12_data_o( m6s12_data_o ), + .s12_addr_o( m6s12_addr ), + .s12_sel_o( m6s12_sel ), + .s12_we_o( m6s12_we ), + .s12_cyc_o( m6s12_cyc ), + .s12_stb_o( m6s12_stb ), + .s12_ack_i( m6s12_ack ), + .s12_err_i( m6s12_err ), + .s12_rty_i( m6s12_rty ), + .s13_data_i( m6s13_data_i ), + .s13_data_o( m6s13_data_o ), + .s13_addr_o( m6s13_addr ), + .s13_sel_o( m6s13_sel ), + .s13_we_o( m6s13_we ), + .s13_cyc_o( m6s13_cyc ), + .s13_stb_o( m6s13_stb ), + .s13_ack_i( m6s13_ack ), + .s13_err_i( m6s13_err ), + .s13_rty_i( m6s13_rty ), + .s14_data_i( m6s14_data_i ), + .s14_data_o( m6s14_data_o ), + .s14_addr_o( m6s14_addr ), + .s14_sel_o( m6s14_sel ), + .s14_we_o( m6s14_we ), + .s14_cyc_o( m6s14_cyc ), + .s14_stb_o( m6s14_stb ), + .s14_ack_i( m6s14_ack ), + .s14_err_i( m6s14_err ), + .s14_rty_i( m6s14_rty ), + .s15_data_i( m6s15_data_i ), + .s15_data_o( m6s15_data_o ), + .s15_addr_o( m6s15_addr ), + .s15_sel_o( m6s15_sel ), + .s15_we_o( m6s15_we ), + .s15_cyc_o( m6s15_cyc ), + .s15_stb_o( m6s15_stb ), + .s15_ack_i( m6s15_ack ), + .s15_err_i( m6s15_err ), + .s15_rty_i( m6s15_rty ) + ); + +wb_conmax_master_if #(dw,aw,sw) m7( + .clk_i( clk_i ), + .rst_i( rst_i ), + .wb_data_i( m7_data_i ), + .wb_data_o( m7_data_o ), + .wb_addr_i( m7_addr_i ), + .wb_sel_i( m7_sel_i ), + .wb_we_i( m7_we_i ), + .wb_cyc_i( m7_cyc_i ), + .wb_stb_i( m7_stb_i ), + .wb_ack_o( m7_ack_o ), + .wb_err_o( m7_err_o ), + .wb_rty_o( m7_rty_o ), + .s0_data_i( m7s0_data_i ), + .s0_data_o( m7s0_data_o ), + .s0_addr_o( m7s0_addr ), + .s0_sel_o( m7s0_sel ), + .s0_we_o( m7s0_we ), + .s0_cyc_o( m7s0_cyc ), + .s0_stb_o( m7s0_stb ), + .s0_ack_i( m7s0_ack ), + .s0_err_i( m7s0_err ), + .s0_rty_i( m7s0_rty ), + .s1_data_i( m7s1_data_i ), + .s1_data_o( m7s1_data_o ), + .s1_addr_o( m7s1_addr ), + .s1_sel_o( m7s1_sel ), + .s1_we_o( m7s1_we ), + .s1_cyc_o( m7s1_cyc ), + .s1_stb_o( m7s1_stb ), + .s1_ack_i( m7s1_ack ), + .s1_err_i( m7s1_err ), + .s1_rty_i( m7s1_rty ), + .s2_data_i( m7s2_data_i ), + .s2_data_o( m7s2_data_o ), + .s2_addr_o( m7s2_addr ), + .s2_sel_o( m7s2_sel ), + .s2_we_o( m7s2_we ), + .s2_cyc_o( m7s2_cyc ), + .s2_stb_o( m7s2_stb ), + .s2_ack_i( m7s2_ack ), + .s2_err_i( m7s2_err ), + .s2_rty_i( m7s2_rty ), + .s3_data_i( m7s3_data_i ), + .s3_data_o( m7s3_data_o ), + .s3_addr_o( m7s3_addr ), + .s3_sel_o( m7s3_sel ), + .s3_we_o( m7s3_we ), + .s3_cyc_o( m7s3_cyc ), + .s3_stb_o( m7s3_stb ), + .s3_ack_i( m7s3_ack ), + .s3_err_i( m7s3_err ), + .s3_rty_i( m7s3_rty ), + .s4_data_i( m7s4_data_i ), + .s4_data_o( m7s4_data_o ), + .s4_addr_o( m7s4_addr ), + .s4_sel_o( m7s4_sel ), + .s4_we_o( m7s4_we ), + .s4_cyc_o( m7s4_cyc ), + .s4_stb_o( m7s4_stb ), + .s4_ack_i( m7s4_ack ), + .s4_err_i( m7s4_err ), + .s4_rty_i( m7s4_rty ), + .s5_data_i( m7s5_data_i ), + .s5_data_o( m7s5_data_o ), + .s5_addr_o( m7s5_addr ), + .s5_sel_o( m7s5_sel ), + .s5_we_o( m7s5_we ), + .s5_cyc_o( m7s5_cyc ), + .s5_stb_o( m7s5_stb ), + .s5_ack_i( m7s5_ack ), + .s5_err_i( m7s5_err ), + .s5_rty_i( m7s5_rty ), + .s6_data_i( m7s6_data_i ), + .s6_data_o( m7s6_data_o ), + .s6_addr_o( m7s6_addr ), + .s6_sel_o( m7s6_sel ), + .s6_we_o( m7s6_we ), + .s6_cyc_o( m7s6_cyc ), + .s6_stb_o( m7s6_stb ), + .s6_ack_i( m7s6_ack ), + .s6_err_i( m7s6_err ), + .s6_rty_i( m7s6_rty ), + .s7_data_i( m7s7_data_i ), + .s7_data_o( m7s7_data_o ), + .s7_addr_o( m7s7_addr ), + .s7_sel_o( m7s7_sel ), + .s7_we_o( m7s7_we ), + .s7_cyc_o( m7s7_cyc ), + .s7_stb_o( m7s7_stb ), + .s7_ack_i( m7s7_ack ), + .s7_err_i( m7s7_err ), + .s7_rty_i( m7s7_rty ), + .s8_data_i( m7s8_data_i ), + .s8_data_o( m7s8_data_o ), + .s8_addr_o( m7s8_addr ), + .s8_sel_o( m7s8_sel ), + .s8_we_o( m7s8_we ), + .s8_cyc_o( m7s8_cyc ), + .s8_stb_o( m7s8_stb ), + .s8_ack_i( m7s8_ack ), + .s8_err_i( m7s8_err ), + .s8_rty_i( m7s8_rty ), + .s9_data_i( m7s9_data_i ), + .s9_data_o( m7s9_data_o ), + .s9_addr_o( m7s9_addr ), + .s9_sel_o( m7s9_sel ), + .s9_we_o( m7s9_we ), + .s9_cyc_o( m7s9_cyc ), + .s9_stb_o( m7s9_stb ), + .s9_ack_i( m7s9_ack ), + .s9_err_i( m7s9_err ), + .s9_rty_i( m7s9_rty ), + .s10_data_i( m7s10_data_i ), + .s10_data_o( m7s10_data_o ), + .s10_addr_o( m7s10_addr ), + .s10_sel_o( m7s10_sel ), + .s10_we_o( m7s10_we ), + .s10_cyc_o( m7s10_cyc ), + .s10_stb_o( m7s10_stb ), + .s10_ack_i( m7s10_ack ), + .s10_err_i( m7s10_err ), + .s10_rty_i( m7s10_rty ), + .s11_data_i( m7s11_data_i ), + .s11_data_o( m7s11_data_o ), + .s11_addr_o( m7s11_addr ), + .s11_sel_o( m7s11_sel ), + .s11_we_o( m7s11_we ), + .s11_cyc_o( m7s11_cyc ), + .s11_stb_o( m7s11_stb ), + .s11_ack_i( m7s11_ack ), + .s11_err_i( m7s11_err ), + .s11_rty_i( m7s11_rty ), + .s12_data_i( m7s12_data_i ), + .s12_data_o( m7s12_data_o ), + .s12_addr_o( m7s12_addr ), + .s12_sel_o( m7s12_sel ), + .s12_we_o( m7s12_we ), + .s12_cyc_o( m7s12_cyc ), + .s12_stb_o( m7s12_stb ), + .s12_ack_i( m7s12_ack ), + .s12_err_i( m7s12_err ), + .s12_rty_i( m7s12_rty ), + .s13_data_i( m7s13_data_i ), + .s13_data_o( m7s13_data_o ), + .s13_addr_o( m7s13_addr ), + .s13_sel_o( m7s13_sel ), + .s13_we_o( m7s13_we ), + .s13_cyc_o( m7s13_cyc ), + .s13_stb_o( m7s13_stb ), + .s13_ack_i( m7s13_ack ), + .s13_err_i( m7s13_err ), + .s13_rty_i( m7s13_rty ), + .s14_data_i( m7s14_data_i ), + .s14_data_o( m7s14_data_o ), + .s14_addr_o( m7s14_addr ), + .s14_sel_o( m7s14_sel ), + .s14_we_o( m7s14_we ), + .s14_cyc_o( m7s14_cyc ), + .s14_stb_o( m7s14_stb ), + .s14_ack_i( m7s14_ack ), + .s14_err_i( m7s14_err ), + .s14_rty_i( m7s14_rty ), + .s15_data_i( m7s15_data_i ), + .s15_data_o( m7s15_data_o ), + .s15_addr_o( m7s15_addr ), + .s15_sel_o( m7s15_sel ), + .s15_we_o( m7s15_we ), + .s15_cyc_o( m7s15_cyc ), + .s15_stb_o( m7s15_stb ), + .s15_ack_i( m7s15_ack ), + .s15_err_i( m7s15_err ), + .s15_rty_i( m7s15_rty ) + ); + +//////////////////////////////////////////////////////////////////// +// +// Slave Interfaces +// + +wb_conmax_slave_if #(pri_sel0,aw,dw,sw) s0( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf0 ), + .wb_data_i( s0_data_i ), + .wb_data_o( s0_data_o ), + .wb_addr_o( s0_addr_o ), + .wb_sel_o( s0_sel_o ), + .wb_we_o( s0_we_o ), + .wb_cyc_o( s0_cyc_o ), + .wb_stb_o( s0_stb_o ), + .wb_ack_i( s0_ack_i ), + .wb_err_i( s0_err_i ), + .wb_rty_i( s0_rty_i ), + .m0_data_i( m0s0_data_o ), + .m0_data_o( m0s0_data_i ), + .m0_addr_i( m0s0_addr ), + .m0_sel_i( m0s0_sel ), + .m0_we_i( m0s0_we ), + .m0_cyc_i( m0s0_cyc ), + .m0_stb_i( m0s0_stb ), + .m0_ack_o( m0s0_ack ), + .m0_err_o( m0s0_err ), + .m0_rty_o( m0s0_rty ), + .m1_data_i( m1s0_data_o ), + .m1_data_o( m1s0_data_i ), + .m1_addr_i( m1s0_addr ), + .m1_sel_i( m1s0_sel ), + .m1_we_i( m1s0_we ), + .m1_cyc_i( m1s0_cyc ), + .m1_stb_i( m1s0_stb ), + .m1_ack_o( m1s0_ack ), + .m1_err_o( m1s0_err ), + .m1_rty_o( m1s0_rty ), + .m2_data_i( m2s0_data_o ), + .m2_data_o( m2s0_data_i ), + .m2_addr_i( m2s0_addr ), + .m2_sel_i( m2s0_sel ), + .m2_we_i( m2s0_we ), + .m2_cyc_i( m2s0_cyc ), + .m2_stb_i( m2s0_stb ), + .m2_ack_o( m2s0_ack ), + .m2_err_o( m2s0_err ), + .m2_rty_o( m2s0_rty ), + .m3_data_i( m3s0_data_o ), + .m3_data_o( m3s0_data_i ), + .m3_addr_i( m3s0_addr ), + .m3_sel_i( m3s0_sel ), + .m3_we_i( m3s0_we ), + .m3_cyc_i( m3s0_cyc ), + .m3_stb_i( m3s0_stb ), + .m3_ack_o( m3s0_ack ), + .m3_err_o( m3s0_err ), + .m3_rty_o( m3s0_rty ), + .m4_data_i( m4s0_data_o ), + .m4_data_o( m4s0_data_i ), + .m4_addr_i( m4s0_addr ), + .m4_sel_i( m4s0_sel ), + .m4_we_i( m4s0_we ), + .m4_cyc_i( m4s0_cyc ), + .m4_stb_i( m4s0_stb ), + .m4_ack_o( m4s0_ack ), + .m4_err_o( m4s0_err ), + .m4_rty_o( m4s0_rty ), + .m5_data_i( m5s0_data_o ), + .m5_data_o( m5s0_data_i ), + .m5_addr_i( m5s0_addr ), + .m5_sel_i( m5s0_sel ), + .m5_we_i( m5s0_we ), + .m5_cyc_i( m5s0_cyc ), + .m5_stb_i( m5s0_stb ), + .m5_ack_o( m5s0_ack ), + .m5_err_o( m5s0_err ), + .m5_rty_o( m5s0_rty ), + .m6_data_i( m6s0_data_o ), + .m6_data_o( m6s0_data_i ), + .m6_addr_i( m6s0_addr ), + .m6_sel_i( m6s0_sel ), + .m6_we_i( m6s0_we ), + .m6_cyc_i( m6s0_cyc ), + .m6_stb_i( m6s0_stb ), + .m6_ack_o( m6s0_ack ), + .m6_err_o( m6s0_err ), + .m6_rty_o( m6s0_rty ), + .m7_data_i( m7s0_data_o ), + .m7_data_o( m7s0_data_i ), + .m7_addr_i( m7s0_addr ), + .m7_sel_i( m7s0_sel ), + .m7_we_i( m7s0_we ), + .m7_cyc_i( m7s0_cyc ), + .m7_stb_i( m7s0_stb ), + .m7_ack_o( m7s0_ack ), + .m7_err_o( m7s0_err ), + .m7_rty_o( m7s0_rty ) + ); + +wb_conmax_slave_if #(pri_sel1,aw,dw,sw) s1( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf1 ), + .wb_data_i( s1_data_i ), + .wb_data_o( s1_data_o ), + .wb_addr_o( s1_addr_o ), + .wb_sel_o( s1_sel_o ), + .wb_we_o( s1_we_o ), + .wb_cyc_o( s1_cyc_o ), + .wb_stb_o( s1_stb_o ), + .wb_ack_i( s1_ack_i ), + .wb_err_i( s1_err_i ), + .wb_rty_i( s1_rty_i ), + .m0_data_i( m0s1_data_o ), + .m0_data_o( m0s1_data_i ), + .m0_addr_i( m0s1_addr ), + .m0_sel_i( m0s1_sel ), + .m0_we_i( m0s1_we ), + .m0_cyc_i( m0s1_cyc ), + .m0_stb_i( m0s1_stb ), + .m0_ack_o( m0s1_ack ), + .m0_err_o( m0s1_err ), + .m0_rty_o( m0s1_rty ), + .m1_data_i( m1s1_data_o ), + .m1_data_o( m1s1_data_i ), + .m1_addr_i( m1s1_addr ), + .m1_sel_i( m1s1_sel ), + .m1_we_i( m1s1_we ), + .m1_cyc_i( m1s1_cyc ), + .m1_stb_i( m1s1_stb ), + .m1_ack_o( m1s1_ack ), + .m1_err_o( m1s1_err ), + .m1_rty_o( m1s1_rty ), + .m2_data_i( m2s1_data_o ), + .m2_data_o( m2s1_data_i ), + .m2_addr_i( m2s1_addr ), + .m2_sel_i( m2s1_sel ), + .m2_we_i( m2s1_we ), + .m2_cyc_i( m2s1_cyc ), + .m2_stb_i( m2s1_stb ), + .m2_ack_o( m2s1_ack ), + .m2_err_o( m2s1_err ), + .m2_rty_o( m2s1_rty ), + .m3_data_i( m3s1_data_o ), + .m3_data_o( m3s1_data_i ), + .m3_addr_i( m3s1_addr ), + .m3_sel_i( m3s1_sel ), + .m3_we_i( m3s1_we ), + .m3_cyc_i( m3s1_cyc ), + .m3_stb_i( m3s1_stb ), + .m3_ack_o( m3s1_ack ), + .m3_err_o( m3s1_err ), + .m3_rty_o( m3s1_rty ), + .m4_data_i( m4s1_data_o ), + .m4_data_o( m4s1_data_i ), + .m4_addr_i( m4s1_addr ), + .m4_sel_i( m4s1_sel ), + .m4_we_i( m4s1_we ), + .m4_cyc_i( m4s1_cyc ), + .m4_stb_i( m4s1_stb ), + .m4_ack_o( m4s1_ack ), + .m4_err_o( m4s1_err ), + .m4_rty_o( m4s1_rty ), + .m5_data_i( m5s1_data_o ), + .m5_data_o( m5s1_data_i ), + .m5_addr_i( m5s1_addr ), + .m5_sel_i( m5s1_sel ), + .m5_we_i( m5s1_we ), + .m5_cyc_i( m5s1_cyc ), + .m5_stb_i( m5s1_stb ), + .m5_ack_o( m5s1_ack ), + .m5_err_o( m5s1_err ), + .m5_rty_o( m5s1_rty ), + .m6_data_i( m6s1_data_o ), + .m6_data_o( m6s1_data_i ), + .m6_addr_i( m6s1_addr ), + .m6_sel_i( m6s1_sel ), + .m6_we_i( m6s1_we ), + .m6_cyc_i( m6s1_cyc ), + .m6_stb_i( m6s1_stb ), + .m6_ack_o( m6s1_ack ), + .m6_err_o( m6s1_err ), + .m6_rty_o( m6s1_rty ), + .m7_data_i( m7s1_data_o ), + .m7_data_o( m7s1_data_i ), + .m7_addr_i( m7s1_addr ), + .m7_sel_i( m7s1_sel ), + .m7_we_i( m7s1_we ), + .m7_cyc_i( m7s1_cyc ), + .m7_stb_i( m7s1_stb ), + .m7_ack_o( m7s1_ack ), + .m7_err_o( m7s1_err ), + .m7_rty_o( m7s1_rty ) + ); + +wb_conmax_slave_if #(pri_sel2,aw,dw,sw) s2( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf2 ), + .wb_data_i( s2_data_i ), + .wb_data_o( s2_data_o ), + .wb_addr_o( s2_addr_o ), + .wb_sel_o( s2_sel_o ), + .wb_we_o( s2_we_o ), + .wb_cyc_o( s2_cyc_o ), + .wb_stb_o( s2_stb_o ), + .wb_ack_i( s2_ack_i ), + .wb_err_i( s2_err_i ), + .wb_rty_i( s2_rty_i ), + .m0_data_i( m0s2_data_o ), + .m0_data_o( m0s2_data_i ), + .m0_addr_i( m0s2_addr ), + .m0_sel_i( m0s2_sel ), + .m0_we_i( m0s2_we ), + .m0_cyc_i( m0s2_cyc ), + .m0_stb_i( m0s2_stb ), + .m0_ack_o( m0s2_ack ), + .m0_err_o( m0s2_err ), + .m0_rty_o( m0s2_rty ), + .m1_data_i( m1s2_data_o ), + .m1_data_o( m1s2_data_i ), + .m1_addr_i( m1s2_addr ), + .m1_sel_i( m1s2_sel ), + .m1_we_i( m1s2_we ), + .m1_cyc_i( m1s2_cyc ), + .m1_stb_i( m1s2_stb ), + .m1_ack_o( m1s2_ack ), + .m1_err_o( m1s2_err ), + .m1_rty_o( m1s2_rty ), + .m2_data_i( m2s2_data_o ), + .m2_data_o( m2s2_data_i ), + .m2_addr_i( m2s2_addr ), + .m2_sel_i( m2s2_sel ), + .m2_we_i( m2s2_we ), + .m2_cyc_i( m2s2_cyc ), + .m2_stb_i( m2s2_stb ), + .m2_ack_o( m2s2_ack ), + .m2_err_o( m2s2_err ), + .m2_rty_o( m2s2_rty ), + .m3_data_i( m3s2_data_o ), + .m3_data_o( m3s2_data_i ), + .m3_addr_i( m3s2_addr ), + .m3_sel_i( m3s2_sel ), + .m3_we_i( m3s2_we ), + .m3_cyc_i( m3s2_cyc ), + .m3_stb_i( m3s2_stb ), + .m3_ack_o( m3s2_ack ), + .m3_err_o( m3s2_err ), + .m3_rty_o( m3s2_rty ), + .m4_data_i( m4s2_data_o ), + .m4_data_o( m4s2_data_i ), + .m4_addr_i( m4s2_addr ), + .m4_sel_i( m4s2_sel ), + .m4_we_i( m4s2_we ), + .m4_cyc_i( m4s2_cyc ), + .m4_stb_i( m4s2_stb ), + .m4_ack_o( m4s2_ack ), + .m4_err_o( m4s2_err ), + .m4_rty_o( m4s2_rty ), + .m5_data_i( m5s2_data_o ), + .m5_data_o( m5s2_data_i ), + .m5_addr_i( m5s2_addr ), + .m5_sel_i( m5s2_sel ), + .m5_we_i( m5s2_we ), + .m5_cyc_i( m5s2_cyc ), + .m5_stb_i( m5s2_stb ), + .m5_ack_o( m5s2_ack ), + .m5_err_o( m5s2_err ), + .m5_rty_o( m5s2_rty ), + .m6_data_i( m6s2_data_o ), + .m6_data_o( m6s2_data_i ), + .m6_addr_i( m6s2_addr ), + .m6_sel_i( m6s2_sel ), + .m6_we_i( m6s2_we ), + .m6_cyc_i( m6s2_cyc ), + .m6_stb_i( m6s2_stb ), + .m6_ack_o( m6s2_ack ), + .m6_err_o( m6s2_err ), + .m6_rty_o( m6s2_rty ), + .m7_data_i( m7s2_data_o ), + .m7_data_o( m7s2_data_i ), + .m7_addr_i( m7s2_addr ), + .m7_sel_i( m7s2_sel ), + .m7_we_i( m7s2_we ), + .m7_cyc_i( m7s2_cyc ), + .m7_stb_i( m7s2_stb ), + .m7_ack_o( m7s2_ack ), + .m7_err_o( m7s2_err ), + .m7_rty_o( m7s2_rty ) + ); + +wb_conmax_slave_if #(pri_sel3,aw,dw,sw) s3( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf3 ), + .wb_data_i( s3_data_i ), + .wb_data_o( s3_data_o ), + .wb_addr_o( s3_addr_o ), + .wb_sel_o( s3_sel_o ), + .wb_we_o( s3_we_o ), + .wb_cyc_o( s3_cyc_o ), + .wb_stb_o( s3_stb_o ), + .wb_ack_i( s3_ack_i ), + .wb_err_i( s3_err_i ), + .wb_rty_i( s3_rty_i ), + .m0_data_i( m0s3_data_o ), + .m0_data_o( m0s3_data_i ), + .m0_addr_i( m0s3_addr ), + .m0_sel_i( m0s3_sel ), + .m0_we_i( m0s3_we ), + .m0_cyc_i( m0s3_cyc ), + .m0_stb_i( m0s3_stb ), + .m0_ack_o( m0s3_ack ), + .m0_err_o( m0s3_err ), + .m0_rty_o( m0s3_rty ), + .m1_data_i( m1s3_data_o ), + .m1_data_o( m1s3_data_i ), + .m1_addr_i( m1s3_addr ), + .m1_sel_i( m1s3_sel ), + .m1_we_i( m1s3_we ), + .m1_cyc_i( m1s3_cyc ), + .m1_stb_i( m1s3_stb ), + .m1_ack_o( m1s3_ack ), + .m1_err_o( m1s3_err ), + .m1_rty_o( m1s3_rty ), + .m2_data_i( m2s3_data_o ), + .m2_data_o( m2s3_data_i ), + .m2_addr_i( m2s3_addr ), + .m2_sel_i( m2s3_sel ), + .m2_we_i( m2s3_we ), + .m2_cyc_i( m2s3_cyc ), + .m2_stb_i( m2s3_stb ), + .m2_ack_o( m2s3_ack ), + .m2_err_o( m2s3_err ), + .m2_rty_o( m2s3_rty ), + .m3_data_i( m3s3_data_o ), + .m3_data_o( m3s3_data_i ), + .m3_addr_i( m3s3_addr ), + .m3_sel_i( m3s3_sel ), + .m3_we_i( m3s3_we ), + .m3_cyc_i( m3s3_cyc ), + .m3_stb_i( m3s3_stb ), + .m3_ack_o( m3s3_ack ), + .m3_err_o( m3s3_err ), + .m3_rty_o( m3s3_rty ), + .m4_data_i( m4s3_data_o ), + .m4_data_o( m4s3_data_i ), + .m4_addr_i( m4s3_addr ), + .m4_sel_i( m4s3_sel ), + .m4_we_i( m4s3_we ), + .m4_cyc_i( m4s3_cyc ), + .m4_stb_i( m4s3_stb ), + .m4_ack_o( m4s3_ack ), + .m4_err_o( m4s3_err ), + .m4_rty_o( m4s3_rty ), + .m5_data_i( m5s3_data_o ), + .m5_data_o( m5s3_data_i ), + .m5_addr_i( m5s3_addr ), + .m5_sel_i( m5s3_sel ), + .m5_we_i( m5s3_we ), + .m5_cyc_i( m5s3_cyc ), + .m5_stb_i( m5s3_stb ), + .m5_ack_o( m5s3_ack ), + .m5_err_o( m5s3_err ), + .m5_rty_o( m5s3_rty ), + .m6_data_i( m6s3_data_o ), + .m6_data_o( m6s3_data_i ), + .m6_addr_i( m6s3_addr ), + .m6_sel_i( m6s3_sel ), + .m6_we_i( m6s3_we ), + .m6_cyc_i( m6s3_cyc ), + .m6_stb_i( m6s3_stb ), + .m6_ack_o( m6s3_ack ), + .m6_err_o( m6s3_err ), + .m6_rty_o( m6s3_rty ), + .m7_data_i( m7s3_data_o ), + .m7_data_o( m7s3_data_i ), + .m7_addr_i( m7s3_addr ), + .m7_sel_i( m7s3_sel ), + .m7_we_i( m7s3_we ), + .m7_cyc_i( m7s3_cyc ), + .m7_stb_i( m7s3_stb ), + .m7_ack_o( m7s3_ack ), + .m7_err_o( m7s3_err ), + .m7_rty_o( m7s3_rty ) + ); + +wb_conmax_slave_if #(pri_sel4,aw,dw,sw) s4( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf4 ), + .wb_data_i( s4_data_i ), + .wb_data_o( s4_data_o ), + .wb_addr_o( s4_addr_o ), + .wb_sel_o( s4_sel_o ), + .wb_we_o( s4_we_o ), + .wb_cyc_o( s4_cyc_o ), + .wb_stb_o( s4_stb_o ), + .wb_ack_i( s4_ack_i ), + .wb_err_i( s4_err_i ), + .wb_rty_i( s4_rty_i ), + .m0_data_i( m0s4_data_o ), + .m0_data_o( m0s4_data_i ), + .m0_addr_i( m0s4_addr ), + .m0_sel_i( m0s4_sel ), + .m0_we_i( m0s4_we ), + .m0_cyc_i( m0s4_cyc ), + .m0_stb_i( m0s4_stb ), + .m0_ack_o( m0s4_ack ), + .m0_err_o( m0s4_err ), + .m0_rty_o( m0s4_rty ), + .m1_data_i( m1s4_data_o ), + .m1_data_o( m1s4_data_i ), + .m1_addr_i( m1s4_addr ), + .m1_sel_i( m1s4_sel ), + .m1_we_i( m1s4_we ), + .m1_cyc_i( m1s4_cyc ), + .m1_stb_i( m1s4_stb ), + .m1_ack_o( m1s4_ack ), + .m1_err_o( m1s4_err ), + .m1_rty_o( m1s4_rty ), + .m2_data_i( m2s4_data_o ), + .m2_data_o( m2s4_data_i ), + .m2_addr_i( m2s4_addr ), + .m2_sel_i( m2s4_sel ), + .m2_we_i( m2s4_we ), + .m2_cyc_i( m2s4_cyc ), + .m2_stb_i( m2s4_stb ), + .m2_ack_o( m2s4_ack ), + .m2_err_o( m2s4_err ), + .m2_rty_o( m2s4_rty ), + .m3_data_i( m3s4_data_o ), + .m3_data_o( m3s4_data_i ), + .m3_addr_i( m3s4_addr ), + .m3_sel_i( m3s4_sel ), + .m3_we_i( m3s4_we ), + .m3_cyc_i( m3s4_cyc ), + .m3_stb_i( m3s4_stb ), + .m3_ack_o( m3s4_ack ), + .m3_err_o( m3s4_err ), + .m3_rty_o( m3s4_rty ), + .m4_data_i( m4s4_data_o ), + .m4_data_o( m4s4_data_i ), + .m4_addr_i( m4s4_addr ), + .m4_sel_i( m4s4_sel ), + .m4_we_i( m4s4_we ), + .m4_cyc_i( m4s4_cyc ), + .m4_stb_i( m4s4_stb ), + .m4_ack_o( m4s4_ack ), + .m4_err_o( m4s4_err ), + .m4_rty_o( m4s4_rty ), + .m5_data_i( m5s4_data_o ), + .m5_data_o( m5s4_data_i ), + .m5_addr_i( m5s4_addr ), + .m5_sel_i( m5s4_sel ), + .m5_we_i( m5s4_we ), + .m5_cyc_i( m5s4_cyc ), + .m5_stb_i( m5s4_stb ), + .m5_ack_o( m5s4_ack ), + .m5_err_o( m5s4_err ), + .m5_rty_o( m5s4_rty ), + .m6_data_i( m6s4_data_o ), + .m6_data_o( m6s4_data_i ), + .m6_addr_i( m6s4_addr ), + .m6_sel_i( m6s4_sel ), + .m6_we_i( m6s4_we ), + .m6_cyc_i( m6s4_cyc ), + .m6_stb_i( m6s4_stb ), + .m6_ack_o( m6s4_ack ), + .m6_err_o( m6s4_err ), + .m6_rty_o( m6s4_rty ), + .m7_data_i( m7s4_data_o ), + .m7_data_o( m7s4_data_i ), + .m7_addr_i( m7s4_addr ), + .m7_sel_i( m7s4_sel ), + .m7_we_i( m7s4_we ), + .m7_cyc_i( m7s4_cyc ), + .m7_stb_i( m7s4_stb ), + .m7_ack_o( m7s4_ack ), + .m7_err_o( m7s4_err ), + .m7_rty_o( m7s4_rty ) + ); + +wb_conmax_slave_if #(pri_sel5,aw,dw,sw) s5( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf5 ), + .wb_data_i( s5_data_i ), + .wb_data_o( s5_data_o ), + .wb_addr_o( s5_addr_o ), + .wb_sel_o( s5_sel_o ), + .wb_we_o( s5_we_o ), + .wb_cyc_o( s5_cyc_o ), + .wb_stb_o( s5_stb_o ), + .wb_ack_i( s5_ack_i ), + .wb_err_i( s5_err_i ), + .wb_rty_i( s5_rty_i ), + .m0_data_i( m0s5_data_o ), + .m0_data_o( m0s5_data_i ), + .m0_addr_i( m0s5_addr ), + .m0_sel_i( m0s5_sel ), + .m0_we_i( m0s5_we ), + .m0_cyc_i( m0s5_cyc ), + .m0_stb_i( m0s5_stb ), + .m0_ack_o( m0s5_ack ), + .m0_err_o( m0s5_err ), + .m0_rty_o( m0s5_rty ), + .m1_data_i( m1s5_data_o ), + .m1_data_o( m1s5_data_i ), + .m1_addr_i( m1s5_addr ), + .m1_sel_i( m1s5_sel ), + .m1_we_i( m1s5_we ), + .m1_cyc_i( m1s5_cyc ), + .m1_stb_i( m1s5_stb ), + .m1_ack_o( m1s5_ack ), + .m1_err_o( m1s5_err ), + .m1_rty_o( m1s5_rty ), + .m2_data_i( m2s5_data_o ), + .m2_data_o( m2s5_data_i ), + .m2_addr_i( m2s5_addr ), + .m2_sel_i( m2s5_sel ), + .m2_we_i( m2s5_we ), + .m2_cyc_i( m2s5_cyc ), + .m2_stb_i( m2s5_stb ), + .m2_ack_o( m2s5_ack ), + .m2_err_o( m2s5_err ), + .m2_rty_o( m2s5_rty ), + .m3_data_i( m3s5_data_o ), + .m3_data_o( m3s5_data_i ), + .m3_addr_i( m3s5_addr ), + .m3_sel_i( m3s5_sel ), + .m3_we_i( m3s5_we ), + .m3_cyc_i( m3s5_cyc ), + .m3_stb_i( m3s5_stb ), + .m3_ack_o( m3s5_ack ), + .m3_err_o( m3s5_err ), + .m3_rty_o( m3s5_rty ), + .m4_data_i( m4s5_data_o ), + .m4_data_o( m4s5_data_i ), + .m4_addr_i( m4s5_addr ), + .m4_sel_i( m4s5_sel ), + .m4_we_i( m4s5_we ), + .m4_cyc_i( m4s5_cyc ), + .m4_stb_i( m4s5_stb ), + .m4_ack_o( m4s5_ack ), + .m4_err_o( m4s5_err ), + .m4_rty_o( m4s5_rty ), + .m5_data_i( m5s5_data_o ), + .m5_data_o( m5s5_data_i ), + .m5_addr_i( m5s5_addr ), + .m5_sel_i( m5s5_sel ), + .m5_we_i( m5s5_we ), + .m5_cyc_i( m5s5_cyc ), + .m5_stb_i( m5s5_stb ), + .m5_ack_o( m5s5_ack ), + .m5_err_o( m5s5_err ), + .m5_rty_o( m5s5_rty ), + .m6_data_i( m6s5_data_o ), + .m6_data_o( m6s5_data_i ), + .m6_addr_i( m6s5_addr ), + .m6_sel_i( m6s5_sel ), + .m6_we_i( m6s5_we ), + .m6_cyc_i( m6s5_cyc ), + .m6_stb_i( m6s5_stb ), + .m6_ack_o( m6s5_ack ), + .m6_err_o( m6s5_err ), + .m6_rty_o( m6s5_rty ), + .m7_data_i( m7s5_data_o ), + .m7_data_o( m7s5_data_i ), + .m7_addr_i( m7s5_addr ), + .m7_sel_i( m7s5_sel ), + .m7_we_i( m7s5_we ), + .m7_cyc_i( m7s5_cyc ), + .m7_stb_i( m7s5_stb ), + .m7_ack_o( m7s5_ack ), + .m7_err_o( m7s5_err ), + .m7_rty_o( m7s5_rty ) + ); + +wb_conmax_slave_if #(pri_sel6,aw,dw,sw) s6( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf6 ), + .wb_data_i( s6_data_i ), + .wb_data_o( s6_data_o ), + .wb_addr_o( s6_addr_o ), + .wb_sel_o( s6_sel_o ), + .wb_we_o( s6_we_o ), + .wb_cyc_o( s6_cyc_o ), + .wb_stb_o( s6_stb_o ), + .wb_ack_i( s6_ack_i ), + .wb_err_i( s6_err_i ), + .wb_rty_i( s6_rty_i ), + .m0_data_i( m0s6_data_o ), + .m0_data_o( m0s6_data_i ), + .m0_addr_i( m0s6_addr ), + .m0_sel_i( m0s6_sel ), + .m0_we_i( m0s6_we ), + .m0_cyc_i( m0s6_cyc ), + .m0_stb_i( m0s6_stb ), + .m0_ack_o( m0s6_ack ), + .m0_err_o( m0s6_err ), + .m0_rty_o( m0s6_rty ), + .m1_data_i( m1s6_data_o ), + .m1_data_o( m1s6_data_i ), + .m1_addr_i( m1s6_addr ), + .m1_sel_i( m1s6_sel ), + .m1_we_i( m1s6_we ), + .m1_cyc_i( m1s6_cyc ), + .m1_stb_i( m1s6_stb ), + .m1_ack_o( m1s6_ack ), + .m1_err_o( m1s6_err ), + .m1_rty_o( m1s6_rty ), + .m2_data_i( m2s6_data_o ), + .m2_data_o( m2s6_data_i ), + .m2_addr_i( m2s6_addr ), + .m2_sel_i( m2s6_sel ), + .m2_we_i( m2s6_we ), + .m2_cyc_i( m2s6_cyc ), + .m2_stb_i( m2s6_stb ), + .m2_ack_o( m2s6_ack ), + .m2_err_o( m2s6_err ), + .m2_rty_o( m2s6_rty ), + .m3_data_i( m3s6_data_o ), + .m3_data_o( m3s6_data_i ), + .m3_addr_i( m3s6_addr ), + .m3_sel_i( m3s6_sel ), + .m3_we_i( m3s6_we ), + .m3_cyc_i( m3s6_cyc ), + .m3_stb_i( m3s6_stb ), + .m3_ack_o( m3s6_ack ), + .m3_err_o( m3s6_err ), + .m3_rty_o( m3s6_rty ), + .m4_data_i( m4s6_data_o ), + .m4_data_o( m4s6_data_i ), + .m4_addr_i( m4s6_addr ), + .m4_sel_i( m4s6_sel ), + .m4_we_i( m4s6_we ), + .m4_cyc_i( m4s6_cyc ), + .m4_stb_i( m4s6_stb ), + .m4_ack_o( m4s6_ack ), + .m4_err_o( m4s6_err ), + .m4_rty_o( m4s6_rty ), + .m5_data_i( m5s6_data_o ), + .m5_data_o( m5s6_data_i ), + .m5_addr_i( m5s6_addr ), + .m5_sel_i( m5s6_sel ), + .m5_we_i( m5s6_we ), + .m5_cyc_i( m5s6_cyc ), + .m5_stb_i( m5s6_stb ), + .m5_ack_o( m5s6_ack ), + .m5_err_o( m5s6_err ), + .m5_rty_o( m5s6_rty ), + .m6_data_i( m6s6_data_o ), + .m6_data_o( m6s6_data_i ), + .m6_addr_i( m6s6_addr ), + .m6_sel_i( m6s6_sel ), + .m6_we_i( m6s6_we ), + .m6_cyc_i( m6s6_cyc ), + .m6_stb_i( m6s6_stb ), + .m6_ack_o( m6s6_ack ), + .m6_err_o( m6s6_err ), + .m6_rty_o( m6s6_rty ), + .m7_data_i( m7s6_data_o ), + .m7_data_o( m7s6_data_i ), + .m7_addr_i( m7s6_addr ), + .m7_sel_i( m7s6_sel ), + .m7_we_i( m7s6_we ), + .m7_cyc_i( m7s6_cyc ), + .m7_stb_i( m7s6_stb ), + .m7_ack_o( m7s6_ack ), + .m7_err_o( m7s6_err ), + .m7_rty_o( m7s6_rty ) + ); + +wb_conmax_slave_if #(pri_sel7,aw,dw,sw) s7( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf7 ), + .wb_data_i( s7_data_i ), + .wb_data_o( s7_data_o ), + .wb_addr_o( s7_addr_o ), + .wb_sel_o( s7_sel_o ), + .wb_we_o( s7_we_o ), + .wb_cyc_o( s7_cyc_o ), + .wb_stb_o( s7_stb_o ), + .wb_ack_i( s7_ack_i ), + .wb_err_i( s7_err_i ), + .wb_rty_i( s7_rty_i ), + .m0_data_i( m0s7_data_o ), + .m0_data_o( m0s7_data_i ), + .m0_addr_i( m0s7_addr ), + .m0_sel_i( m0s7_sel ), + .m0_we_i( m0s7_we ), + .m0_cyc_i( m0s7_cyc ), + .m0_stb_i( m0s7_stb ), + .m0_ack_o( m0s7_ack ), + .m0_err_o( m0s7_err ), + .m0_rty_o( m0s7_rty ), + .m1_data_i( m1s7_data_o ), + .m1_data_o( m1s7_data_i ), + .m1_addr_i( m1s7_addr ), + .m1_sel_i( m1s7_sel ), + .m1_we_i( m1s7_we ), + .m1_cyc_i( m1s7_cyc ), + .m1_stb_i( m1s7_stb ), + .m1_ack_o( m1s7_ack ), + .m1_err_o( m1s7_err ), + .m1_rty_o( m1s7_rty ), + .m2_data_i( m2s7_data_o ), + .m2_data_o( m2s7_data_i ), + .m2_addr_i( m2s7_addr ), + .m2_sel_i( m2s7_sel ), + .m2_we_i( m2s7_we ), + .m2_cyc_i( m2s7_cyc ), + .m2_stb_i( m2s7_stb ), + .m2_ack_o( m2s7_ack ), + .m2_err_o( m2s7_err ), + .m2_rty_o( m2s7_rty ), + .m3_data_i( m3s7_data_o ), + .m3_data_o( m3s7_data_i ), + .m3_addr_i( m3s7_addr ), + .m3_sel_i( m3s7_sel ), + .m3_we_i( m3s7_we ), + .m3_cyc_i( m3s7_cyc ), + .m3_stb_i( m3s7_stb ), + .m3_ack_o( m3s7_ack ), + .m3_err_o( m3s7_err ), + .m3_rty_o( m3s7_rty ), + .m4_data_i( m4s7_data_o ), + .m4_data_o( m4s7_data_i ), + .m4_addr_i( m4s7_addr ), + .m4_sel_i( m4s7_sel ), + .m4_we_i( m4s7_we ), + .m4_cyc_i( m4s7_cyc ), + .m4_stb_i( m4s7_stb ), + .m4_ack_o( m4s7_ack ), + .m4_err_o( m4s7_err ), + .m4_rty_o( m4s7_rty ), + .m5_data_i( m5s7_data_o ), + .m5_data_o( m5s7_data_i ), + .m5_addr_i( m5s7_addr ), + .m5_sel_i( m5s7_sel ), + .m5_we_i( m5s7_we ), + .m5_cyc_i( m5s7_cyc ), + .m5_stb_i( m5s7_stb ), + .m5_ack_o( m5s7_ack ), + .m5_err_o( m5s7_err ), + .m5_rty_o( m5s7_rty ), + .m6_data_i( m6s7_data_o ), + .m6_data_o( m6s7_data_i ), + .m6_addr_i( m6s7_addr ), + .m6_sel_i( m6s7_sel ), + .m6_we_i( m6s7_we ), + .m6_cyc_i( m6s7_cyc ), + .m6_stb_i( m6s7_stb ), + .m6_ack_o( m6s7_ack ), + .m6_err_o( m6s7_err ), + .m6_rty_o( m6s7_rty ), + .m7_data_i( m7s7_data_o ), + .m7_data_o( m7s7_data_i ), + .m7_addr_i( m7s7_addr ), + .m7_sel_i( m7s7_sel ), + .m7_we_i( m7s7_we ), + .m7_cyc_i( m7s7_cyc ), + .m7_stb_i( m7s7_stb ), + .m7_ack_o( m7s7_ack ), + .m7_err_o( m7s7_err ), + .m7_rty_o( m7s7_rty ) + ); + +wb_conmax_slave_if #(pri_sel8,aw,dw,sw) s8( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf8 ), + .wb_data_i( s8_data_i ), + .wb_data_o( s8_data_o ), + .wb_addr_o( s8_addr_o ), + .wb_sel_o( s8_sel_o ), + .wb_we_o( s8_we_o ), + .wb_cyc_o( s8_cyc_o ), + .wb_stb_o( s8_stb_o ), + .wb_ack_i( s8_ack_i ), + .wb_err_i( s8_err_i ), + .wb_rty_i( s8_rty_i ), + .m0_data_i( m0s8_data_o ), + .m0_data_o( m0s8_data_i ), + .m0_addr_i( m0s8_addr ), + .m0_sel_i( m0s8_sel ), + .m0_we_i( m0s8_we ), + .m0_cyc_i( m0s8_cyc ), + .m0_stb_i( m0s8_stb ), + .m0_ack_o( m0s8_ack ), + .m0_err_o( m0s8_err ), + .m0_rty_o( m0s8_rty ), + .m1_data_i( m1s8_data_o ), + .m1_data_o( m1s8_data_i ), + .m1_addr_i( m1s8_addr ), + .m1_sel_i( m1s8_sel ), + .m1_we_i( m1s8_we ), + .m1_cyc_i( m1s8_cyc ), + .m1_stb_i( m1s8_stb ), + .m1_ack_o( m1s8_ack ), + .m1_err_o( m1s8_err ), + .m1_rty_o( m1s8_rty ), + .m2_data_i( m2s8_data_o ), + .m2_data_o( m2s8_data_i ), + .m2_addr_i( m2s8_addr ), + .m2_sel_i( m2s8_sel ), + .m2_we_i( m2s8_we ), + .m2_cyc_i( m2s8_cyc ), + .m2_stb_i( m2s8_stb ), + .m2_ack_o( m2s8_ack ), + .m2_err_o( m2s8_err ), + .m2_rty_o( m2s8_rty ), + .m3_data_i( m3s8_data_o ), + .m3_data_o( m3s8_data_i ), + .m3_addr_i( m3s8_addr ), + .m3_sel_i( m3s8_sel ), + .m3_we_i( m3s8_we ), + .m3_cyc_i( m3s8_cyc ), + .m3_stb_i( m3s8_stb ), + .m3_ack_o( m3s8_ack ), + .m3_err_o( m3s8_err ), + .m3_rty_o( m3s8_rty ), + .m4_data_i( m4s8_data_o ), + .m4_data_o( m4s8_data_i ), + .m4_addr_i( m4s8_addr ), + .m4_sel_i( m4s8_sel ), + .m4_we_i( m4s8_we ), + .m4_cyc_i( m4s8_cyc ), + .m4_stb_i( m4s8_stb ), + .m4_ack_o( m4s8_ack ), + .m4_err_o( m4s8_err ), + .m4_rty_o( m4s8_rty ), + .m5_data_i( m5s8_data_o ), + .m5_data_o( m5s8_data_i ), + .m5_addr_i( m5s8_addr ), + .m5_sel_i( m5s8_sel ), + .m5_we_i( m5s8_we ), + .m5_cyc_i( m5s8_cyc ), + .m5_stb_i( m5s8_stb ), + .m5_ack_o( m5s8_ack ), + .m5_err_o( m5s8_err ), + .m5_rty_o( m5s8_rty ), + .m6_data_i( m6s8_data_o ), + .m6_data_o( m6s8_data_i ), + .m6_addr_i( m6s8_addr ), + .m6_sel_i( m6s8_sel ), + .m6_we_i( m6s8_we ), + .m6_cyc_i( m6s8_cyc ), + .m6_stb_i( m6s8_stb ), + .m6_ack_o( m6s8_ack ), + .m6_err_o( m6s8_err ), + .m6_rty_o( m6s8_rty ), + .m7_data_i( m7s8_data_o ), + .m7_data_o( m7s8_data_i ), + .m7_addr_i( m7s8_addr ), + .m7_sel_i( m7s8_sel ), + .m7_we_i( m7s8_we ), + .m7_cyc_i( m7s8_cyc ), + .m7_stb_i( m7s8_stb ), + .m7_ack_o( m7s8_ack ), + .m7_err_o( m7s8_err ), + .m7_rty_o( m7s8_rty ) + ); + +wb_conmax_slave_if #(pri_sel9,aw,dw,sw) s9( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf9 ), + .wb_data_i( s9_data_i ), + .wb_data_o( s9_data_o ), + .wb_addr_o( s9_addr_o ), + .wb_sel_o( s9_sel_o ), + .wb_we_o( s9_we_o ), + .wb_cyc_o( s9_cyc_o ), + .wb_stb_o( s9_stb_o ), + .wb_ack_i( s9_ack_i ), + .wb_err_i( s9_err_i ), + .wb_rty_i( s9_rty_i ), + .m0_data_i( m0s9_data_o ), + .m0_data_o( m0s9_data_i ), + .m0_addr_i( m0s9_addr ), + .m0_sel_i( m0s9_sel ), + .m0_we_i( m0s9_we ), + .m0_cyc_i( m0s9_cyc ), + .m0_stb_i( m0s9_stb ), + .m0_ack_o( m0s9_ack ), + .m0_err_o( m0s9_err ), + .m0_rty_o( m0s9_rty ), + .m1_data_i( m1s9_data_o ), + .m1_data_o( m1s9_data_i ), + .m1_addr_i( m1s9_addr ), + .m1_sel_i( m1s9_sel ), + .m1_we_i( m1s9_we ), + .m1_cyc_i( m1s9_cyc ), + .m1_stb_i( m1s9_stb ), + .m1_ack_o( m1s9_ack ), + .m1_err_o( m1s9_err ), + .m1_rty_o( m1s9_rty ), + .m2_data_i( m2s9_data_o ), + .m2_data_o( m2s9_data_i ), + .m2_addr_i( m2s9_addr ), + .m2_sel_i( m2s9_sel ), + .m2_we_i( m2s9_we ), + .m2_cyc_i( m2s9_cyc ), + .m2_stb_i( m2s9_stb ), + .m2_ack_o( m2s9_ack ), + .m2_err_o( m2s9_err ), + .m2_rty_o( m2s9_rty ), + .m3_data_i( m3s9_data_o ), + .m3_data_o( m3s9_data_i ), + .m3_addr_i( m3s9_addr ), + .m3_sel_i( m3s9_sel ), + .m3_we_i( m3s9_we ), + .m3_cyc_i( m3s9_cyc ), + .m3_stb_i( m3s9_stb ), + .m3_ack_o( m3s9_ack ), + .m3_err_o( m3s9_err ), + .m3_rty_o( m3s9_rty ), + .m4_data_i( m4s9_data_o ), + .m4_data_o( m4s9_data_i ), + .m4_addr_i( m4s9_addr ), + .m4_sel_i( m4s9_sel ), + .m4_we_i( m4s9_we ), + .m4_cyc_i( m4s9_cyc ), + .m4_stb_i( m4s9_stb ), + .m4_ack_o( m4s9_ack ), + .m4_err_o( m4s9_err ), + .m4_rty_o( m4s9_rty ), + .m5_data_i( m5s9_data_o ), + .m5_data_o( m5s9_data_i ), + .m5_addr_i( m5s9_addr ), + .m5_sel_i( m5s9_sel ), + .m5_we_i( m5s9_we ), + .m5_cyc_i( m5s9_cyc ), + .m5_stb_i( m5s9_stb ), + .m5_ack_o( m5s9_ack ), + .m5_err_o( m5s9_err ), + .m5_rty_o( m5s9_rty ), + .m6_data_i( m6s9_data_o ), + .m6_data_o( m6s9_data_i ), + .m6_addr_i( m6s9_addr ), + .m6_sel_i( m6s9_sel ), + .m6_we_i( m6s9_we ), + .m6_cyc_i( m6s9_cyc ), + .m6_stb_i( m6s9_stb ), + .m6_ack_o( m6s9_ack ), + .m6_err_o( m6s9_err ), + .m6_rty_o( m6s9_rty ), + .m7_data_i( m7s9_data_o ), + .m7_data_o( m7s9_data_i ), + .m7_addr_i( m7s9_addr ), + .m7_sel_i( m7s9_sel ), + .m7_we_i( m7s9_we ), + .m7_cyc_i( m7s9_cyc ), + .m7_stb_i( m7s9_stb ), + .m7_ack_o( m7s9_ack ), + .m7_err_o( m7s9_err ), + .m7_rty_o( m7s9_rty ) + ); + +wb_conmax_slave_if #(pri_sel10,aw,dw,sw) s10( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf10 ), + .wb_data_i( s10_data_i ), + .wb_data_o( s10_data_o ), + .wb_addr_o( s10_addr_o ), + .wb_sel_o( s10_sel_o ), + .wb_we_o( s10_we_o ), + .wb_cyc_o( s10_cyc_o ), + .wb_stb_o( s10_stb_o ), + .wb_ack_i( s10_ack_i ), + .wb_err_i( s10_err_i ), + .wb_rty_i( s10_rty_i ), + .m0_data_i( m0s10_data_o ), + .m0_data_o( m0s10_data_i ), + .m0_addr_i( m0s10_addr ), + .m0_sel_i( m0s10_sel ), + .m0_we_i( m0s10_we ), + .m0_cyc_i( m0s10_cyc ), + .m0_stb_i( m0s10_stb ), + .m0_ack_o( m0s10_ack ), + .m0_err_o( m0s10_err ), + .m0_rty_o( m0s10_rty ), + .m1_data_i( m1s10_data_o ), + .m1_data_o( m1s10_data_i ), + .m1_addr_i( m1s10_addr ), + .m1_sel_i( m1s10_sel ), + .m1_we_i( m1s10_we ), + .m1_cyc_i( m1s10_cyc ), + .m1_stb_i( m1s10_stb ), + .m1_ack_o( m1s10_ack ), + .m1_err_o( m1s10_err ), + .m1_rty_o( m1s10_rty ), + .m2_data_i( m2s10_data_o ), + .m2_data_o( m2s10_data_i ), + .m2_addr_i( m2s10_addr ), + .m2_sel_i( m2s10_sel ), + .m2_we_i( m2s10_we ), + .m2_cyc_i( m2s10_cyc ), + .m2_stb_i( m2s10_stb ), + .m2_ack_o( m2s10_ack ), + .m2_err_o( m2s10_err ), + .m2_rty_o( m2s10_rty ), + .m3_data_i( m3s10_data_o ), + .m3_data_o( m3s10_data_i ), + .m3_addr_i( m3s10_addr ), + .m3_sel_i( m3s10_sel ), + .m3_we_i( m3s10_we ), + .m3_cyc_i( m3s10_cyc ), + .m3_stb_i( m3s10_stb ), + .m3_ack_o( m3s10_ack ), + .m3_err_o( m3s10_err ), + .m3_rty_o( m3s10_rty ), + .m4_data_i( m4s10_data_o ), + .m4_data_o( m4s10_data_i ), + .m4_addr_i( m4s10_addr ), + .m4_sel_i( m4s10_sel ), + .m4_we_i( m4s10_we ), + .m4_cyc_i( m4s10_cyc ), + .m4_stb_i( m4s10_stb ), + .m4_ack_o( m4s10_ack ), + .m4_err_o( m4s10_err ), + .m4_rty_o( m4s10_rty ), + .m5_data_i( m5s10_data_o ), + .m5_data_o( m5s10_data_i ), + .m5_addr_i( m5s10_addr ), + .m5_sel_i( m5s10_sel ), + .m5_we_i( m5s10_we ), + .m5_cyc_i( m5s10_cyc ), + .m5_stb_i( m5s10_stb ), + .m5_ack_o( m5s10_ack ), + .m5_err_o( m5s10_err ), + .m5_rty_o( m5s10_rty ), + .m6_data_i( m6s10_data_o ), + .m6_data_o( m6s10_data_i ), + .m6_addr_i( m6s10_addr ), + .m6_sel_i( m6s10_sel ), + .m6_we_i( m6s10_we ), + .m6_cyc_i( m6s10_cyc ), + .m6_stb_i( m6s10_stb ), + .m6_ack_o( m6s10_ack ), + .m6_err_o( m6s10_err ), + .m6_rty_o( m6s10_rty ), + .m7_data_i( m7s10_data_o ), + .m7_data_o( m7s10_data_i ), + .m7_addr_i( m7s10_addr ), + .m7_sel_i( m7s10_sel ), + .m7_we_i( m7s10_we ), + .m7_cyc_i( m7s10_cyc ), + .m7_stb_i( m7s10_stb ), + .m7_ack_o( m7s10_ack ), + .m7_err_o( m7s10_err ), + .m7_rty_o( m7s10_rty ) + ); + +wb_conmax_slave_if #(pri_sel11,aw,dw,sw) s11( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf11 ), + .wb_data_i( s11_data_i ), + .wb_data_o( s11_data_o ), + .wb_addr_o( s11_addr_o ), + .wb_sel_o( s11_sel_o ), + .wb_we_o( s11_we_o ), + .wb_cyc_o( s11_cyc_o ), + .wb_stb_o( s11_stb_o ), + .wb_ack_i( s11_ack_i ), + .wb_err_i( s11_err_i ), + .wb_rty_i( s11_rty_i ), + .m0_data_i( m0s11_data_o ), + .m0_data_o( m0s11_data_i ), + .m0_addr_i( m0s11_addr ), + .m0_sel_i( m0s11_sel ), + .m0_we_i( m0s11_we ), + .m0_cyc_i( m0s11_cyc ), + .m0_stb_i( m0s11_stb ), + .m0_ack_o( m0s11_ack ), + .m0_err_o( m0s11_err ), + .m0_rty_o( m0s11_rty ), + .m1_data_i( m1s11_data_o ), + .m1_data_o( m1s11_data_i ), + .m1_addr_i( m1s11_addr ), + .m1_sel_i( m1s11_sel ), + .m1_we_i( m1s11_we ), + .m1_cyc_i( m1s11_cyc ), + .m1_stb_i( m1s11_stb ), + .m1_ack_o( m1s11_ack ), + .m1_err_o( m1s11_err ), + .m1_rty_o( m1s11_rty ), + .m2_data_i( m2s11_data_o ), + .m2_data_o( m2s11_data_i ), + .m2_addr_i( m2s11_addr ), + .m2_sel_i( m2s11_sel ), + .m2_we_i( m2s11_we ), + .m2_cyc_i( m2s11_cyc ), + .m2_stb_i( m2s11_stb ), + .m2_ack_o( m2s11_ack ), + .m2_err_o( m2s11_err ), + .m2_rty_o( m2s11_rty ), + .m3_data_i( m3s11_data_o ), + .m3_data_o( m3s11_data_i ), + .m3_addr_i( m3s11_addr ), + .m3_sel_i( m3s11_sel ), + .m3_we_i( m3s11_we ), + .m3_cyc_i( m3s11_cyc ), + .m3_stb_i( m3s11_stb ), + .m3_ack_o( m3s11_ack ), + .m3_err_o( m3s11_err ), + .m3_rty_o( m3s11_rty ), + .m4_data_i( m4s11_data_o ), + .m4_data_o( m4s11_data_i ), + .m4_addr_i( m4s11_addr ), + .m4_sel_i( m4s11_sel ), + .m4_we_i( m4s11_we ), + .m4_cyc_i( m4s11_cyc ), + .m4_stb_i( m4s11_stb ), + .m4_ack_o( m4s11_ack ), + .m4_err_o( m4s11_err ), + .m4_rty_o( m4s11_rty ), + .m5_data_i( m5s11_data_o ), + .m5_data_o( m5s11_data_i ), + .m5_addr_i( m5s11_addr ), + .m5_sel_i( m5s11_sel ), + .m5_we_i( m5s11_we ), + .m5_cyc_i( m5s11_cyc ), + .m5_stb_i( m5s11_stb ), + .m5_ack_o( m5s11_ack ), + .m5_err_o( m5s11_err ), + .m5_rty_o( m5s11_rty ), + .m6_data_i( m6s11_data_o ), + .m6_data_o( m6s11_data_i ), + .m6_addr_i( m6s11_addr ), + .m6_sel_i( m6s11_sel ), + .m6_we_i( m6s11_we ), + .m6_cyc_i( m6s11_cyc ), + .m6_stb_i( m6s11_stb ), + .m6_ack_o( m6s11_ack ), + .m6_err_o( m6s11_err ), + .m6_rty_o( m6s11_rty ), + .m7_data_i( m7s11_data_o ), + .m7_data_o( m7s11_data_i ), + .m7_addr_i( m7s11_addr ), + .m7_sel_i( m7s11_sel ), + .m7_we_i( m7s11_we ), + .m7_cyc_i( m7s11_cyc ), + .m7_stb_i( m7s11_stb ), + .m7_ack_o( m7s11_ack ), + .m7_err_o( m7s11_err ), + .m7_rty_o( m7s11_rty ) + ); + +wb_conmax_slave_if #(pri_sel12,aw,dw,sw) s12( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf12 ), + .wb_data_i( s12_data_i ), + .wb_data_o( s12_data_o ), + .wb_addr_o( s12_addr_o ), + .wb_sel_o( s12_sel_o ), + .wb_we_o( s12_we_o ), + .wb_cyc_o( s12_cyc_o ), + .wb_stb_o( s12_stb_o ), + .wb_ack_i( s12_ack_i ), + .wb_err_i( s12_err_i ), + .wb_rty_i( s12_rty_i ), + .m0_data_i( m0s12_data_o ), + .m0_data_o( m0s12_data_i ), + .m0_addr_i( m0s12_addr ), + .m0_sel_i( m0s12_sel ), + .m0_we_i( m0s12_we ), + .m0_cyc_i( m0s12_cyc ), + .m0_stb_i( m0s12_stb ), + .m0_ack_o( m0s12_ack ), + .m0_err_o( m0s12_err ), + .m0_rty_o( m0s12_rty ), + .m1_data_i( m1s12_data_o ), + .m1_data_o( m1s12_data_i ), + .m1_addr_i( m1s12_addr ), + .m1_sel_i( m1s12_sel ), + .m1_we_i( m1s12_we ), + .m1_cyc_i( m1s12_cyc ), + .m1_stb_i( m1s12_stb ), + .m1_ack_o( m1s12_ack ), + .m1_err_o( m1s12_err ), + .m1_rty_o( m1s12_rty ), + .m2_data_i( m2s12_data_o ), + .m2_data_o( m2s12_data_i ), + .m2_addr_i( m2s12_addr ), + .m2_sel_i( m2s12_sel ), + .m2_we_i( m2s12_we ), + .m2_cyc_i( m2s12_cyc ), + .m2_stb_i( m2s12_stb ), + .m2_ack_o( m2s12_ack ), + .m2_err_o( m2s12_err ), + .m2_rty_o( m2s12_rty ), + .m3_data_i( m3s12_data_o ), + .m3_data_o( m3s12_data_i ), + .m3_addr_i( m3s12_addr ), + .m3_sel_i( m3s12_sel ), + .m3_we_i( m3s12_we ), + .m3_cyc_i( m3s12_cyc ), + .m3_stb_i( m3s12_stb ), + .m3_ack_o( m3s12_ack ), + .m3_err_o( m3s12_err ), + .m3_rty_o( m3s12_rty ), + .m4_data_i( m4s12_data_o ), + .m4_data_o( m4s12_data_i ), + .m4_addr_i( m4s12_addr ), + .m4_sel_i( m4s12_sel ), + .m4_we_i( m4s12_we ), + .m4_cyc_i( m4s12_cyc ), + .m4_stb_i( m4s12_stb ), + .m4_ack_o( m4s12_ack ), + .m4_err_o( m4s12_err ), + .m4_rty_o( m4s12_rty ), + .m5_data_i( m5s12_data_o ), + .m5_data_o( m5s12_data_i ), + .m5_addr_i( m5s12_addr ), + .m5_sel_i( m5s12_sel ), + .m5_we_i( m5s12_we ), + .m5_cyc_i( m5s12_cyc ), + .m5_stb_i( m5s12_stb ), + .m5_ack_o( m5s12_ack ), + .m5_err_o( m5s12_err ), + .m5_rty_o( m5s12_rty ), + .m6_data_i( m6s12_data_o ), + .m6_data_o( m6s12_data_i ), + .m6_addr_i( m6s12_addr ), + .m6_sel_i( m6s12_sel ), + .m6_we_i( m6s12_we ), + .m6_cyc_i( m6s12_cyc ), + .m6_stb_i( m6s12_stb ), + .m6_ack_o( m6s12_ack ), + .m6_err_o( m6s12_err ), + .m6_rty_o( m6s12_rty ), + .m7_data_i( m7s12_data_o ), + .m7_data_o( m7s12_data_i ), + .m7_addr_i( m7s12_addr ), + .m7_sel_i( m7s12_sel ), + .m7_we_i( m7s12_we ), + .m7_cyc_i( m7s12_cyc ), + .m7_stb_i( m7s12_stb ), + .m7_ack_o( m7s12_ack ), + .m7_err_o( m7s12_err ), + .m7_rty_o( m7s12_rty ) + ); + +wb_conmax_slave_if #(pri_sel13,aw,dw,sw) s13( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf13 ), + .wb_data_i( s13_data_i ), + .wb_data_o( s13_data_o ), + .wb_addr_o( s13_addr_o ), + .wb_sel_o( s13_sel_o ), + .wb_we_o( s13_we_o ), + .wb_cyc_o( s13_cyc_o ), + .wb_stb_o( s13_stb_o ), + .wb_ack_i( s13_ack_i ), + .wb_err_i( s13_err_i ), + .wb_rty_i( s13_rty_i ), + .m0_data_i( m0s13_data_o ), + .m0_data_o( m0s13_data_i ), + .m0_addr_i( m0s13_addr ), + .m0_sel_i( m0s13_sel ), + .m0_we_i( m0s13_we ), + .m0_cyc_i( m0s13_cyc ), + .m0_stb_i( m0s13_stb ), + .m0_ack_o( m0s13_ack ), + .m0_err_o( m0s13_err ), + .m0_rty_o( m0s13_rty ), + .m1_data_i( m1s13_data_o ), + .m1_data_o( m1s13_data_i ), + .m1_addr_i( m1s13_addr ), + .m1_sel_i( m1s13_sel ), + .m1_we_i( m1s13_we ), + .m1_cyc_i( m1s13_cyc ), + .m1_stb_i( m1s13_stb ), + .m1_ack_o( m1s13_ack ), + .m1_err_o( m1s13_err ), + .m1_rty_o( m1s13_rty ), + .m2_data_i( m2s13_data_o ), + .m2_data_o( m2s13_data_i ), + .m2_addr_i( m2s13_addr ), + .m2_sel_i( m2s13_sel ), + .m2_we_i( m2s13_we ), + .m2_cyc_i( m2s13_cyc ), + .m2_stb_i( m2s13_stb ), + .m2_ack_o( m2s13_ack ), + .m2_err_o( m2s13_err ), + .m2_rty_o( m2s13_rty ), + .m3_data_i( m3s13_data_o ), + .m3_data_o( m3s13_data_i ), + .m3_addr_i( m3s13_addr ), + .m3_sel_i( m3s13_sel ), + .m3_we_i( m3s13_we ), + .m3_cyc_i( m3s13_cyc ), + .m3_stb_i( m3s13_stb ), + .m3_ack_o( m3s13_ack ), + .m3_err_o( m3s13_err ), + .m3_rty_o( m3s13_rty ), + .m4_data_i( m4s13_data_o ), + .m4_data_o( m4s13_data_i ), + .m4_addr_i( m4s13_addr ), + .m4_sel_i( m4s13_sel ), + .m4_we_i( m4s13_we ), + .m4_cyc_i( m4s13_cyc ), + .m4_stb_i( m4s13_stb ), + .m4_ack_o( m4s13_ack ), + .m4_err_o( m4s13_err ), + .m4_rty_o( m4s13_rty ), + .m5_data_i( m5s13_data_o ), + .m5_data_o( m5s13_data_i ), + .m5_addr_i( m5s13_addr ), + .m5_sel_i( m5s13_sel ), + .m5_we_i( m5s13_we ), + .m5_cyc_i( m5s13_cyc ), + .m5_stb_i( m5s13_stb ), + .m5_ack_o( m5s13_ack ), + .m5_err_o( m5s13_err ), + .m5_rty_o( m5s13_rty ), + .m6_data_i( m6s13_data_o ), + .m6_data_o( m6s13_data_i ), + .m6_addr_i( m6s13_addr ), + .m6_sel_i( m6s13_sel ), + .m6_we_i( m6s13_we ), + .m6_cyc_i( m6s13_cyc ), + .m6_stb_i( m6s13_stb ), + .m6_ack_o( m6s13_ack ), + .m6_err_o( m6s13_err ), + .m6_rty_o( m6s13_rty ), + .m7_data_i( m7s13_data_o ), + .m7_data_o( m7s13_data_i ), + .m7_addr_i( m7s13_addr ), + .m7_sel_i( m7s13_sel ), + .m7_we_i( m7s13_we ), + .m7_cyc_i( m7s13_cyc ), + .m7_stb_i( m7s13_stb ), + .m7_ack_o( m7s13_ack ), + .m7_err_o( m7s13_err ), + .m7_rty_o( m7s13_rty ) + ); + +wb_conmax_slave_if #(pri_sel14,aw,dw,sw) s14( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf14 ), + .wb_data_i( s14_data_i ), + .wb_data_o( s14_data_o ), + .wb_addr_o( s14_addr_o ), + .wb_sel_o( s14_sel_o ), + .wb_we_o( s14_we_o ), + .wb_cyc_o( s14_cyc_o ), + .wb_stb_o( s14_stb_o ), + .wb_ack_i( s14_ack_i ), + .wb_err_i( s14_err_i ), + .wb_rty_i( s14_rty_i ), + .m0_data_i( m0s14_data_o ), + .m0_data_o( m0s14_data_i ), + .m0_addr_i( m0s14_addr ), + .m0_sel_i( m0s14_sel ), + .m0_we_i( m0s14_we ), + .m0_cyc_i( m0s14_cyc ), + .m0_stb_i( m0s14_stb ), + .m0_ack_o( m0s14_ack ), + .m0_err_o( m0s14_err ), + .m0_rty_o( m0s14_rty ), + .m1_data_i( m1s14_data_o ), + .m1_data_o( m1s14_data_i ), + .m1_addr_i( m1s14_addr ), + .m1_sel_i( m1s14_sel ), + .m1_we_i( m1s14_we ), + .m1_cyc_i( m1s14_cyc ), + .m1_stb_i( m1s14_stb ), + .m1_ack_o( m1s14_ack ), + .m1_err_o( m1s14_err ), + .m1_rty_o( m1s14_rty ), + .m2_data_i( m2s14_data_o ), + .m2_data_o( m2s14_data_i ), + .m2_addr_i( m2s14_addr ), + .m2_sel_i( m2s14_sel ), + .m2_we_i( m2s14_we ), + .m2_cyc_i( m2s14_cyc ), + .m2_stb_i( m2s14_stb ), + .m2_ack_o( m2s14_ack ), + .m2_err_o( m2s14_err ), + .m2_rty_o( m2s14_rty ), + .m3_data_i( m3s14_data_o ), + .m3_data_o( m3s14_data_i ), + .m3_addr_i( m3s14_addr ), + .m3_sel_i( m3s14_sel ), + .m3_we_i( m3s14_we ), + .m3_cyc_i( m3s14_cyc ), + .m3_stb_i( m3s14_stb ), + .m3_ack_o( m3s14_ack ), + .m3_err_o( m3s14_err ), + .m3_rty_o( m3s14_rty ), + .m4_data_i( m4s14_data_o ), + .m4_data_o( m4s14_data_i ), + .m4_addr_i( m4s14_addr ), + .m4_sel_i( m4s14_sel ), + .m4_we_i( m4s14_we ), + .m4_cyc_i( m4s14_cyc ), + .m4_stb_i( m4s14_stb ), + .m4_ack_o( m4s14_ack ), + .m4_err_o( m4s14_err ), + .m4_rty_o( m4s14_rty ), + .m5_data_i( m5s14_data_o ), + .m5_data_o( m5s14_data_i ), + .m5_addr_i( m5s14_addr ), + .m5_sel_i( m5s14_sel ), + .m5_we_i( m5s14_we ), + .m5_cyc_i( m5s14_cyc ), + .m5_stb_i( m5s14_stb ), + .m5_ack_o( m5s14_ack ), + .m5_err_o( m5s14_err ), + .m5_rty_o( m5s14_rty ), + .m6_data_i( m6s14_data_o ), + .m6_data_o( m6s14_data_i ), + .m6_addr_i( m6s14_addr ), + .m6_sel_i( m6s14_sel ), + .m6_we_i( m6s14_we ), + .m6_cyc_i( m6s14_cyc ), + .m6_stb_i( m6s14_stb ), + .m6_ack_o( m6s14_ack ), + .m6_err_o( m6s14_err ), + .m6_rty_o( m6s14_rty ), + .m7_data_i( m7s14_data_o ), + .m7_data_o( m7s14_data_i ), + .m7_addr_i( m7s14_addr ), + .m7_sel_i( m7s14_sel ), + .m7_we_i( m7s14_we ), + .m7_cyc_i( m7s14_cyc ), + .m7_stb_i( m7s14_stb ), + .m7_ack_o( m7s14_ack ), + .m7_err_o( m7s14_err ), + .m7_rty_o( m7s14_rty ) + ); + +wb_conmax_slave_if #(pri_sel15,aw,dw,sw) s15( + .clk_i( clk_i ), + .rst_i( rst_i ), + .conf( conf15 ), + .wb_data_i( i_s15_data_i ), + .wb_data_o( i_s15_data_o ), + .wb_addr_o( i_s15_addr_o ), + .wb_sel_o( i_s15_sel_o ), + .wb_we_o( i_s15_we_o ), + .wb_cyc_o( i_s15_cyc_o ), + .wb_stb_o( i_s15_stb_o ), + .wb_ack_i( i_s15_ack_i ), + .wb_err_i( i_s15_err_i ), + .wb_rty_i( i_s15_rty_i ), + .m0_data_i( m0s15_data_o ), + .m0_data_o( m0s15_data_i ), + .m0_addr_i( m0s15_addr ), + .m0_sel_i( m0s15_sel ), + .m0_we_i( m0s15_we ), + .m0_cyc_i( m0s15_cyc ), + .m0_stb_i( m0s15_stb ), + .m0_ack_o( m0s15_ack ), + .m0_err_o( m0s15_err ), + .m0_rty_o( m0s15_rty ), + .m1_data_i( m1s15_data_o ), + .m1_data_o( m1s15_data_i ), + .m1_addr_i( m1s15_addr ), + .m1_sel_i( m1s15_sel ), + .m1_we_i( m1s15_we ), + .m1_cyc_i( m1s15_cyc ), + .m1_stb_i( m1s15_stb ), + .m1_ack_o( m1s15_ack ), + .m1_err_o( m1s15_err ), + .m1_rty_o( m1s15_rty ), + .m2_data_i( m2s15_data_o ), + .m2_data_o( m2s15_data_i ), + .m2_addr_i( m2s15_addr ), + .m2_sel_i( m2s15_sel ), + .m2_we_i( m2s15_we ), + .m2_cyc_i( m2s15_cyc ), + .m2_stb_i( m2s15_stb ), + .m2_ack_o( m2s15_ack ), + .m2_err_o( m2s15_err ), + .m2_rty_o( m2s15_rty ), + .m3_data_i( m3s15_data_o ), + .m3_data_o( m3s15_data_i ), + .m3_addr_i( m3s15_addr ), + .m3_sel_i( m3s15_sel ), + .m3_we_i( m3s15_we ), + .m3_cyc_i( m3s15_cyc ), + .m3_stb_i( m3s15_stb ), + .m3_ack_o( m3s15_ack ), + .m3_err_o( m3s15_err ), + .m3_rty_o( m3s15_rty ), + .m4_data_i( m4s15_data_o ), + .m4_data_o( m4s15_data_i ), + .m4_addr_i( m4s15_addr ), + .m4_sel_i( m4s15_sel ), + .m4_we_i( m4s15_we ), + .m4_cyc_i( m4s15_cyc ), + .m4_stb_i( m4s15_stb ), + .m4_ack_o( m4s15_ack ), + .m4_err_o( m4s15_err ), + .m4_rty_o( m4s15_rty ), + .m5_data_i( m5s15_data_o ), + .m5_data_o( m5s15_data_i ), + .m5_addr_i( m5s15_addr ), + .m5_sel_i( m5s15_sel ), + .m5_we_i( m5s15_we ), + .m5_cyc_i( m5s15_cyc ), + .m5_stb_i( m5s15_stb ), + .m5_ack_o( m5s15_ack ), + .m5_err_o( m5s15_err ), + .m5_rty_o( m5s15_rty ), + .m6_data_i( m6s15_data_o ), + .m6_data_o( m6s15_data_i ), + .m6_addr_i( m6s15_addr ), + .m6_sel_i( m6s15_sel ), + .m6_we_i( m6s15_we ), + .m6_cyc_i( m6s15_cyc ), + .m6_stb_i( m6s15_stb ), + .m6_ack_o( m6s15_ack ), + .m6_err_o( m6s15_err ), + .m6_rty_o( m6s15_rty ), + .m7_data_i( m7s15_data_o ), + .m7_data_o( m7s15_data_i ), + .m7_addr_i( m7s15_addr ), + .m7_sel_i( m7s15_sel ), + .m7_we_i( m7s15_we ), + .m7_cyc_i( m7s15_cyc ), + .m7_stb_i( m7s15_stb ), + .m7_ack_o( m7s15_ack ), + .m7_err_o( m7s15_err ), + .m7_rty_o( m7s15_rty ) + ); + +wb_conmax_rf #(rf_addr,dw,aw,sw) rf( + .clk_i( clk_i ), + .rst_i( rst_i ), + .i_wb_data_i( i_s15_data_o ), + .i_wb_data_o( i_s15_data_i ), + .i_wb_addr_i( i_s15_addr_o ), + .i_wb_sel_i( i_s15_sel_o ), + .i_wb_we_i( i_s15_we_o ), + .i_wb_cyc_i( i_s15_cyc_o ), + .i_wb_stb_i( i_s15_stb_o ), + .i_wb_ack_o( i_s15_ack_i ), + .i_wb_err_o( i_s15_err_i ), + .i_wb_rty_o( i_s15_rty_i ), + + .e_wb_data_i( s15_data_i ), + .e_wb_data_o( s15_data_o ), + .e_wb_addr_o( s15_addr_o ), + .e_wb_sel_o( s15_sel_o ), + .e_wb_we_o( s15_we_o ), + .e_wb_cyc_o( s15_cyc_o ), + .e_wb_stb_o( s15_stb_o ), + .e_wb_ack_i( s15_ack_i ), + .e_wb_err_i( s15_err_i ), + .e_wb_rty_i( s15_rty_i ), + + .conf0( conf0 ), + .conf1( conf1 ), + .conf2( conf2 ), + .conf3( conf3 ), + .conf4( conf4 ), + .conf5( conf5 ), + .conf6( conf6 ), + .conf7( conf7 ), + .conf8( conf8 ), + .conf9( conf9 ), + .conf10( conf10 ), + .conf11( conf11 ), + .conf12( conf12 ), + .conf13( conf13 ), + .conf14( conf14 ), + .conf15( conf15 ) + ); +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v new file mode 100644 index 000000000..06ccf8b32 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v @@ -0,0 +1,2157 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Channel Arbiter //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_ch_arb.v,v 1.2 2002/02/01 01:54:44 rudi Exp $ +// +// $Date: 2002/02/01 01:54:44 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_ch_arb.v,v $ +// Revision 1.2 2002/02/01 01:54:44 rudi +// +// - Minor cleanup +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.4 2001/06/14 08:51:25 rudi +// +// +// Changed Module name to match file name. +// +// Revision 1.3 2001/06/13 02:26:46 rudi +// +// +// Small changes after running lint. +// +// Revision 1.2 2001/06/05 10:22:34 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:47 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +// Arbiter +// +// Implements a simple round robin arbiter for DMA channels of +// same priority + +module wb_dma_ch_arb(clk, rst, req, gnt, advance); + +input clk; +input rst; +input [30:0] req; // Req input +output [4:0] gnt; // Grant output +input advance; // Next Target + +/////////////////////////////////////////////////////////////////////// +// +// Definitions +// + +parameter [4:0] + grant0 = 5'h0, + grant1 = 5'h1, + grant2 = 5'h2, + grant3 = 5'h3, + grant4 = 5'h4, + grant5 = 5'h5, + grant6 = 5'h6, + grant7 = 5'h7, + grant8 = 5'h8, + grant9 = 5'h9, + grant10 = 5'ha, + grant11 = 5'hb, + grant12 = 5'hc, + grant13 = 5'hd, + grant14 = 5'he, + grant15 = 5'hf, + grant16 = 5'h10, + grant17 = 5'h11, + grant18 = 5'h12, + grant19 = 5'h13, + grant20 = 5'h14, + grant21 = 5'h15, + grant22 = 5'h16, + grant23 = 5'h17, + grant24 = 5'h18, + grant25 = 5'h19, + grant26 = 5'h1a, + grant27 = 5'h1b, + grant28 = 5'h1c, + grant29 = 5'h1d, + grant30 = 5'h1e; + +/////////////////////////////////////////////////////////////////////// +// +// Local Registers and Wires +// + +reg [4:0] state, next_state; + +/////////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign gnt = state; + +always@(posedge clk or negedge rst) + if(!rst) state <= #1 grant0; + else state <= #1 next_state; + +/////////////////////////////////////////////////////////////////////// +// +// Next State Logic +// - implements round robin arbitration algorithm +// - switches grant if current req is dropped or next is asserted +// - parks at last grant +// + +always@(state or req or advance) + begin + next_state = state; // Default Keep State + case(state) // synopsys parallel_case full_case + grant0: + // if this req is dropped or next is asserted, check for other req's + if(!req[0] | advance) + begin + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + end + grant1: + // if this req is dropped or next is asserted, check for other req's + if(!req[1] | advance) + begin + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + end + grant2: + // if this req is dropped or next is asserted, check for other req's + if(!req[2] | advance) + begin + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + end + grant3: + // if this req is dropped or next is asserted, check for other req's + if(!req[3] | advance) + begin + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + end + grant4: + // if this req is dropped or next is asserted, check for other req's + if(!req[4] | advance) + begin + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + end + grant5: + // if this req is dropped or next is asserted, check for other req's + if(!req[5] | advance) + begin + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + end + grant6: + // if this req is dropped or next is asserted, check for other req's + if(!req[6] | advance) + begin + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + end + grant7: + // if this req is dropped or next is asserted, check for other req's + if(!req[7] | advance) + begin + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + end + grant8: + // if this req is dropped or next is asserted, check for other req's + if(!req[8] | advance) + begin + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + end + grant9: + // if this req is dropped or next is asserted, check for other req's + if(!req[9] | advance) + begin + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + end + grant10: + // if this req is dropped or next is asserted, check for other req's + if(!req[10] | advance) + begin + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + end + grant11: + // if this req is dropped or next is asserted, check for other req's + if(!req[11] | advance) + begin + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + end + grant12: + // if this req is dropped or next is asserted, check for other req's + if(!req[12] | advance) + begin + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + end + grant13: + // if this req is dropped or next is asserted, check for other req's + if(!req[13] | advance) + begin + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + end + grant14: + // if this req is dropped or next is asserted, check for other req's + if(!req[14] | advance) + begin + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + end + grant15: + // if this req is dropped or next is asserted, check for other req's + if(!req[15] | advance) + begin + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + end + grant16: + // if this req is dropped or next is asserted, check for other req's + if(!req[16] | advance) + begin + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + end + grant17: + // if this req is dropped or next is asserted, check for other req's + if(!req[17] | advance) + begin + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + end + grant18: + // if this req is dropped or next is asserted, check for other req's + if(!req[18] | advance) + begin + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + end + grant19: + // if this req is dropped or next is asserted, check for other req's + if(!req[19] | advance) + begin + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + end + grant20: + // if this req is dropped or next is asserted, check for other req's + if(!req[20] | advance) + begin + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + end + grant21: + // if this req is dropped or next is asserted, check for other req's + if(!req[21] | advance) + begin + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + end + grant22: + // if this req is dropped or next is asserted, check for other req's + if(!req[22] | advance) + begin + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + end + grant23: + // if this req is dropped or next is asserted, check for other req's + if(!req[23] | advance) + begin + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + end + grant24: + // if this req is dropped or next is asserted, check for other req's + if(!req[24] | advance) + begin + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + end + grant25: + // if this req is dropped or next is asserted, check for other req's + if(!req[25] | advance) + begin + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + end + grant26: + // if this req is dropped or next is asserted, check for other req's + if(!req[26] | advance) + begin + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + end + grant27: + // if this req is dropped or next is asserted, check for other req's + if(!req[27] | advance) + begin + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + end + grant28: + // if this req is dropped or next is asserted, check for other req's + if(!req[28] | advance) + begin + if(req[29]) next_state = grant29; + else + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + end + grant29: + // if this req is dropped or next is asserted, check for other req's + if(!req[29] | advance) + begin + if(req[30]) next_state = grant30; + else + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + end + grant30: + // if this req is dropped or next is asserted, check for other req's + if(!req[30] | advance) + begin + if(req[0]) next_state = grant0; + else + if(req[1]) next_state = grant1; + else + if(req[2]) next_state = grant2; + else + if(req[3]) next_state = grant3; + else + if(req[4]) next_state = grant4; + else + if(req[5]) next_state = grant5; + else + if(req[6]) next_state = grant6; + else + if(req[7]) next_state = grant7; + else + if(req[8]) next_state = grant8; + else + if(req[9]) next_state = grant9; + else + if(req[10]) next_state = grant10; + else + if(req[11]) next_state = grant11; + else + if(req[12]) next_state = grant12; + else + if(req[13]) next_state = grant13; + else + if(req[14]) next_state = grant14; + else + if(req[15]) next_state = grant15; + else + if(req[16]) next_state = grant16; + else + if(req[17]) next_state = grant17; + else + if(req[18]) next_state = grant18; + else + if(req[19]) next_state = grant19; + else + if(req[20]) next_state = grant20; + else + if(req[21]) next_state = grant21; + else + if(req[22]) next_state = grant22; + else + if(req[23]) next_state = grant23; + else + if(req[24]) next_state = grant24; + else + if(req[25]) next_state = grant25; + else + if(req[26]) next_state = grant26; + else + if(req[27]) next_state = grant27; + else + if(req[28]) next_state = grant28; + else + if(req[29]) next_state = grant29; + end + endcase + end + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v new file mode 100644 index 000000000..88427eca1 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v @@ -0,0 +1,384 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Priority Encoder //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_ch_pri_enc.v,v 1.5 2002/02/01 01:54:44 rudi Exp $ +// +// $Date: 2002/02/01 01:54:44 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_ch_pri_enc.v,v $ +// Revision 1.5 2002/02/01 01:54:44 rudi +// +// - Minor cleanup +// +// Revision 1.4 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.3 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.2 2001/08/07 08:00:43 rudi +// +// +// Split up priority encoder modules to separate files +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:36 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:50 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +// Priority Encoder +// +// Determines the channel with the highest priority, also takes +// the valid bit in consideration + +module wb_dma_ch_pri_enc(clk, valid, + pri0, pri1, pri2, pri3, + pri4, pri5, pri6, pri7, + pri8, pri9, pri10, pri11, + pri12, pri13, pri14, pri15, + pri16, pri17, pri18, pri19, + pri20, pri21, pri22, pri23, + pri24, pri25, pri26, pri27, + pri28, pri29, pri30, + pri_out); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +// chXX_conf = { CBUF, ED, ARS, EN } +parameter [1:0] pri_sel = 2'd0; +parameter [3:0] ch0_conf = 4'h1; +parameter [3:0] ch1_conf = 4'h0; +parameter [3:0] ch2_conf = 4'h0; +parameter [3:0] ch3_conf = 4'h0; +parameter [3:0] ch4_conf = 4'h0; +parameter [3:0] ch5_conf = 4'h0; +parameter [3:0] ch6_conf = 4'h0; +parameter [3:0] ch7_conf = 4'h0; +parameter [3:0] ch8_conf = 4'h0; +parameter [3:0] ch9_conf = 4'h0; +parameter [3:0] ch10_conf = 4'h0; +parameter [3:0] ch11_conf = 4'h0; +parameter [3:0] ch12_conf = 4'h0; +parameter [3:0] ch13_conf = 4'h0; +parameter [3:0] ch14_conf = 4'h0; +parameter [3:0] ch15_conf = 4'h0; +parameter [3:0] ch16_conf = 4'h0; +parameter [3:0] ch17_conf = 4'h0; +parameter [3:0] ch18_conf = 4'h0; +parameter [3:0] ch19_conf = 4'h0; +parameter [3:0] ch20_conf = 4'h0; +parameter [3:0] ch21_conf = 4'h0; +parameter [3:0] ch22_conf = 4'h0; +parameter [3:0] ch23_conf = 4'h0; +parameter [3:0] ch24_conf = 4'h0; +parameter [3:0] ch25_conf = 4'h0; +parameter [3:0] ch26_conf = 4'h0; +parameter [3:0] ch27_conf = 4'h0; +parameter [3:0] ch28_conf = 4'h0; +parameter [3:0] ch29_conf = 4'h0; +parameter [3:0] ch30_conf = 4'h0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk; +input [30:0] valid; // Channel Valid bits +input [2:0] pri0, pri1, pri2, pri3; // Channel Priorities +input [2:0] pri4, pri5, pri6, pri7; +input [2:0] pri8, pri9, pri10, pri11; +input [2:0] pri12, pri13, pri14, pri15; +input [2:0] pri16, pri17, pri18, pri19; +input [2:0] pri20, pri21, pri22, pri23; +input [2:0] pri24, pri25, pri26, pri27; +input [2:0] pri28, pri29, pri30; +output [2:0] pri_out; // Highest unserviced priority + +wire [7:0] pri0_out, pri1_out, pri2_out, pri3_out; +wire [7:0] pri4_out, pri5_out, pri6_out, pri7_out; +wire [7:0] pri8_out, pri9_out, pri10_out, pri11_out; +wire [7:0] pri12_out, pri13_out, pri14_out, pri15_out; +wire [7:0] pri16_out, pri17_out, pri18_out, pri19_out; +wire [7:0] pri20_out, pri21_out, pri22_out, pri23_out; +wire [7:0] pri24_out, pri25_out, pri26_out, pri27_out; +wire [7:0] pri28_out, pri29_out, pri30_out; + +wire [7:0] pri_out_tmp; +reg [2:0] pri_out; +reg [2:0] pri_out2; +reg [2:0] pri_out1; +reg [2:0] pri_out0; + +wb_dma_pri_enc_sub #(ch1_conf,pri_sel) u0( // Use channel config 1 for channel 0 encoder + .valid( valid[0] ), + .pri_in( pri0 ), + .pri_out( pri0_out ) + ); +wb_dma_pri_enc_sub #(ch1_conf,pri_sel) u1( + .valid( valid[1] ), + .pri_in( pri1 ), + .pri_out( pri1_out ) + ); +wb_dma_pri_enc_sub #(ch2_conf,pri_sel) u2( + .valid( valid[2] ), + .pri_in( pri2 ), + .pri_out( pri2_out ) + ); +wb_dma_pri_enc_sub #(ch3_conf,pri_sel) u3( + .valid( valid[3] ), + .pri_in( pri3 ), + .pri_out( pri3_out ) + ); +wb_dma_pri_enc_sub #(ch4_conf,pri_sel) u4( + .valid( valid[4] ), + .pri_in( pri4 ), + .pri_out( pri4_out ) + ); +wb_dma_pri_enc_sub #(ch5_conf,pri_sel) u5( + .valid( valid[5] ), + .pri_in( pri5 ), + .pri_out( pri5_out ) + ); +wb_dma_pri_enc_sub #(ch6_conf,pri_sel) u6( + .valid( valid[6] ), + .pri_in( pri6 ), + .pri_out( pri6_out ) + ); +wb_dma_pri_enc_sub #(ch7_conf,pri_sel) u7( + .valid( valid[7] ), + .pri_in( pri7 ), + .pri_out( pri7_out ) + ); +wb_dma_pri_enc_sub #(ch8_conf,pri_sel) u8( + .valid( valid[8] ), + .pri_in( pri8 ), + .pri_out( pri8_out ) + ); +wb_dma_pri_enc_sub #(ch9_conf,pri_sel) u9( + .valid( valid[9] ), + .pri_in( pri9 ), + .pri_out( pri9_out ) + ); +wb_dma_pri_enc_sub #(ch10_conf,pri_sel) u10( + .valid( valid[10] ), + .pri_in( pri10 ), + .pri_out( pri10_out ) + ); +wb_dma_pri_enc_sub #(ch11_conf,pri_sel) u11( + .valid( valid[11] ), + .pri_in( pri11 ), + .pri_out( pri11_out ) + ); +wb_dma_pri_enc_sub #(ch12_conf,pri_sel) u12( + .valid( valid[12] ), + .pri_in( pri12 ), + .pri_out( pri12_out ) + ); +wb_dma_pri_enc_sub #(ch13_conf,pri_sel) u13( + .valid( valid[13] ), + .pri_in( pri13 ), + .pri_out( pri13_out ) + ); +wb_dma_pri_enc_sub #(ch14_conf,pri_sel) u14( + .valid( valid[14] ), + .pri_in( pri14 ), + .pri_out( pri14_out ) + ); +wb_dma_pri_enc_sub #(ch15_conf,pri_sel) u15( + .valid( valid[15] ), + .pri_in( pri15 ), + .pri_out( pri15_out ) + ); +wb_dma_pri_enc_sub #(ch16_conf,pri_sel) u16( + .valid( valid[16] ), + .pri_in( pri16 ), + .pri_out( pri16_out ) + ); +wb_dma_pri_enc_sub #(ch17_conf,pri_sel) u17( + .valid( valid[17] ), + .pri_in( pri17 ), + .pri_out( pri17_out ) + ); +wb_dma_pri_enc_sub #(ch18_conf,pri_sel) u18( + .valid( valid[18] ), + .pri_in( pri18 ), + .pri_out( pri18_out ) + ); +wb_dma_pri_enc_sub #(ch19_conf,pri_sel) u19( + .valid( valid[19] ), + .pri_in( pri19 ), + .pri_out( pri19_out ) + ); +wb_dma_pri_enc_sub #(ch20_conf,pri_sel) u20( + .valid( valid[20] ), + .pri_in( pri20 ), + .pri_out( pri20_out ) + ); +wb_dma_pri_enc_sub #(ch21_conf,pri_sel) u21( + .valid( valid[21] ), + .pri_in( pri21 ), + .pri_out( pri21_out ) + ); +wb_dma_pri_enc_sub #(ch22_conf,pri_sel) u22( + .valid( valid[22] ), + .pri_in( pri22 ), + .pri_out( pri22_out ) + ); +wb_dma_pri_enc_sub #(ch23_conf,pri_sel) u23( + .valid( valid[23] ), + .pri_in( pri23 ), + .pri_out( pri23_out ) + ); +wb_dma_pri_enc_sub #(ch24_conf,pri_sel) u24( + .valid( valid[24] ), + .pri_in( pri24 ), + .pri_out( pri24_out ) + ); +wb_dma_pri_enc_sub #(ch25_conf,pri_sel) u25( + .valid( valid[25] ), + .pri_in( pri25 ), + .pri_out( pri25_out ) + ); +wb_dma_pri_enc_sub #(ch26_conf,pri_sel) u26( + .valid( valid[26] ), + .pri_in( pri26 ), + .pri_out( pri26_out ) + ); +wb_dma_pri_enc_sub #(ch27_conf,pri_sel) u27( + .valid( valid[27] ), + .pri_in( pri27 ), + .pri_out( pri27_out ) + ); +wb_dma_pri_enc_sub #(ch28_conf,pri_sel) u28( + .valid( valid[28] ), + .pri_in( pri28 ), + .pri_out( pri28_out ) + ); +wb_dma_pri_enc_sub #(ch29_conf,pri_sel) u29( + .valid( valid[29] ), + .pri_in( pri29 ), + .pri_out( pri29_out ) + ); +wb_dma_pri_enc_sub #(ch30_conf,pri_sel) u30( + .valid( valid[30] ), + .pri_in( pri30 ), + .pri_out( pri30_out ) + ); + +assign pri_out_tmp = pri0_out | pri1_out | pri2_out | pri3_out | + pri4_out | pri5_out | pri6_out | pri7_out | + pri8_out | pri9_out | pri10_out | pri11_out | + pri12_out | pri13_out | pri14_out | pri15_out | + pri16_out | pri17_out | pri18_out | pri19_out | + pri20_out | pri21_out | pri22_out | pri23_out | + pri24_out | pri25_out | pri26_out | pri27_out | + pri28_out | pri29_out | pri30_out; + +// 8 Priority Levels +always @(posedge clk) + if(pri_out_tmp[7]) pri_out2 <= #1 3'h7; + else + if(pri_out_tmp[6]) pri_out2 <= #1 3'h6; + else + if(pri_out_tmp[5]) pri_out2 <= #1 3'h5; + else + if(pri_out_tmp[4]) pri_out2 <= #1 3'h4; + else + if(pri_out_tmp[3]) pri_out2 <= #1 3'h3; + else + if(pri_out_tmp[2]) pri_out2 <= #1 3'h2; + else + if(pri_out_tmp[1]) pri_out2 <= #1 3'h1; + else pri_out2 <= #1 3'h0; + +// 4 Priority Levels +always @(posedge clk) + if(pri_out_tmp[3]) pri_out1 <= #1 3'h3; + else + if(pri_out_tmp[2]) pri_out1 <= #1 3'h2; + else + if(pri_out_tmp[1]) pri_out1 <= #1 3'h1; + else pri_out1 <= #1 3'h0; + +// 2 Priority Levels +always @(posedge clk) + if(pri_out_tmp[1]) pri_out0 <= #1 3'h1; + else pri_out0 <= #1 3'h0; + +// Select configured priority +always @(pri_sel or pri_out0 or pri_out1 or pri_out2) + case(pri_sel) // synopsys parallel_case full_case + 2'd0: pri_out = pri_out0; + 2'd1: pri_out = pri_out1; + 2'd2: pri_out = pri_out2; + endcase + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v new file mode 100644 index 000000000..fa580cafb --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v @@ -0,0 +1,587 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA One Channel Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_ch_rf.v,v 1.5 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_ch_rf.v,v $ +// Revision 1.5 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.4 2001/10/30 02:06:17 rudi +// +// - Fixed problem where synthesis tools would instantiate latches instead of flip-flops +// +// Revision 1.3 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.3 2001/06/14 08:50:01 rudi +// +// Changed Module Name to match file name. +// +// Revision 1.2 2001/06/13 02:26:48 rudi +// +// +// Small changes after running lint. +// +// Revision 1.1 2001/06/05 10:25:27 rudi +// +// +// Initial checkin of register file for one channel. +// +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_ch_rf( clk, rst, + pointer, pointer_s, ch_csr, ch_txsz, ch_adr0, ch_adr1, + ch_am0, ch_am1, sw_pointer, ch_stop, ch_dis, int, + + wb_rf_din, wb_rf_adr, wb_rf_we, wb_rf_re, + + // DMA Registers Write Back Channel Select + ch_sel, ndnr, + + // DMA Engine Status + dma_busy, dma_err, dma_done, dma_done_all, + + // DMA Engine Reg File Update ctrl signals + de_csr, de_txsz, de_adr0, de_adr1, + de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, + de_fetch_descr, dma_rest, + ptr_set + + ); + +parameter [4:0] CH_NO = 5'h0; // This Instances Channel ID +parameter [0:0] CH_EN = 1'b1; // This channel exists +parameter [0:0] HAVE_ARS = 1'b1; // 1=this Instance Supports ARS +parameter [0:0] HAVE_ED = 1'b1; // 1=this Instance Supports External Descriptors +parameter [0:0] HAVE_CBUF= 1'b1; // 1=this Instance Supports Cyclic Buffers + +input clk, rst; + +output [31:0] pointer; +output [31:0] pointer_s; +output [31:0] ch_csr; +output [31:0] ch_txsz; +output [31:0] ch_adr0; +output [31:0] ch_adr1; +output [31:0] ch_am0; +output [31:0] ch_am1; +output [31:0] sw_pointer; +output ch_stop; +output ch_dis; +output int; + +input [31:0] wb_rf_din; +input [7:0] wb_rf_adr; +input wb_rf_we; +input wb_rf_re; + +input [4:0] ch_sel; +input ndnr; + +// DMA Engine Status +input dma_busy, dma_err, dma_done, dma_done_all; + +// DMA Engine Reg File Update ctrl signals +input [31:0] de_csr; +input [11:0] de_txsz; +input [31:0] de_adr0; +input [31:0] de_adr1; +input de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, ptr_set; +input de_fetch_descr; +input dma_rest; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +wire [31:0] pointer; +reg [27:0] pointer_r; +reg [27:0] pointer_sr; +reg ptr_valid; +reg ch_eol; + +wire [31:0] ch_csr, ch_txsz; + +reg [8:0] ch_csr_r; +reg [2:0] ch_csr_r2; +reg [2:0] ch_csr_r3; +reg [2:0] int_src_r; +reg ch_err_r; +reg ch_stop; +reg ch_busy; +reg ch_done; +reg ch_err; +reg rest_en; + +reg [10:0] ch_chk_sz_r; +reg [11:0] ch_tot_sz_r; +reg [22:0] ch_txsz_s; +reg ch_sz_inf; + +wire [31:0] ch_adr0, ch_adr1; +reg [29:0] ch_adr0_r, ch_adr1_r; +wire [31:0] ch_am0, ch_am1; +reg [27:0] ch_am0_r, ch_am1_r; + +reg [29:0] ch_adr0_s, ch_adr1_s; + +reg [29:0] sw_pointer_r; +wire sw_pointer_we; +wire [28:0] cmp_adr; +reg ch_dis; +wire ch_enable; + +wire pointer_we; +wire ch_csr_we, ch_csr_re, ch_txsz_we, ch_adr0_we, ch_adr1_we; +wire ch_am0_we, ch_am1_we; +reg ch_rl; +wire ch_done_we; +wire ch_err_we; +wire chunk_done_we; + +wire ch_csr_dewe, ch_txsz_dewe, ch_adr0_dewe, ch_adr1_dewe; + +wire this_ptr_set; +wire ptr_inv; + +//////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign ch_adr0 = CH_EN ? {ch_adr0_r, 2'h0} : 32'h0; +assign ch_adr1 = CH_EN ? {ch_adr1_r, 2'h0} : 32'h0; +assign ch_am0 = (CH_EN & HAVE_CBUF) ? {ch_am0_r, 4'h0} : 32'hffff_fff0; +assign ch_am1 = (CH_EN & HAVE_CBUF) ? {ch_am1_r, 4'h0} : 32'hffff_fff0; +assign sw_pointer = (CH_EN & HAVE_CBUF) ? {sw_pointer_r,2'h0} : 32'h0; + +assign pointer = CH_EN ? {pointer_r, 3'h0, ptr_valid} : 32'h0; +assign pointer_s = CH_EN ? {pointer_sr, 4'h0} : 32'h0; +assign ch_csr = CH_EN ? {9'h0, int_src_r, ch_csr_r3, rest_en, ch_csr_r2, + ch_err, ch_done, ch_busy, 1'b0, ch_csr_r[8:1], ch_enable} : 32'h0; +assign ch_txsz = CH_EN ? {5'h0, ch_chk_sz_r, ch_sz_inf, 3'h0, ch_tot_sz_r} : 32'h0; + +assign ch_enable = CH_EN ? (ch_csr_r[`WDMA_CH_EN] & (HAVE_CBUF ? !ch_dis : 1'b1) ) : 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// CH0 control signals +// + +parameter [4:0] CH_ADR = CH_NO + 5'h1; + +assign ch_csr_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h0); +assign ch_csr_re = CH_EN & wb_rf_re & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h0); +assign ch_txsz_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h1); +assign ch_adr0_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h2); +assign ch_am0_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h3); +assign ch_adr1_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h4); +assign ch_am1_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h5); +assign pointer_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h6); +assign sw_pointer_we = CH_EN & wb_rf_we & (wb_rf_adr[7:3] == CH_ADR) & (wb_rf_adr[2:0] == 3'h7); + +assign ch_done_we = CH_EN & (((ch_sel==CH_NO) & dma_done_all) | ndnr) & + (ch_csr[`WDMA_USE_ED] ? ch_eol : !ch_csr[`WDMA_ARS]); +assign chunk_done_we = CH_EN & (ch_sel==CH_NO) & dma_done; +assign ch_err_we = CH_EN & (ch_sel==CH_NO) & dma_err; +assign ch_csr_dewe = CH_EN & de_csr_we & (ch_sel==CH_NO); +assign ch_txsz_dewe = CH_EN & de_txsz_we & (ch_sel==CH_NO); +assign ch_adr0_dewe = CH_EN & de_adr0_we & (ch_sel==CH_NO); +assign ch_adr1_dewe = CH_EN & de_adr1_we & (ch_sel==CH_NO); + +assign ptr_inv = CH_EN & ((ch_sel==CH_NO) & dma_done_all) | ndnr; +assign this_ptr_set = CH_EN & ptr_set & (ch_sel==CH_NO); + +always @(posedge clk) + ch_rl <= #1 CH_EN & HAVE_ARS & ( + (rest_en & dma_rest) | + ((ch_sel==CH_NO) & dma_done_all & ch_csr[`WDMA_ARS] & !ch_csr[`WDMA_USE_ED]) + ); + +// --------------------------------------------------- +// Pointers + +always @(posedge clk or negedge rst) + if(!rst) ptr_valid <= #1 1'b0; + else + if(CH_EN & HAVE_ED) + begin + if( this_ptr_set | (rest_en & dma_rest) ) + ptr_valid <= #1 1'b1; + else + if(ptr_inv) ptr_valid <= #1 1'b0; + end + else ptr_valid <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) ch_eol <= #1 1'b0; + else + if(CH_EN & HAVE_ED) + begin + if(ch_csr_dewe) ch_eol <= #1 de_csr[`WDMA_ED_EOL]; + else + if(ch_done_we) ch_eol <= #1 1'b0; + end + else ch_eol <= #1 1'b0; + +always @(posedge clk) + if(CH_EN & HAVE_ED) + begin + if(pointer_we) pointer_r <= #1 wb_rf_din[31:4]; + else + if(this_ptr_set) pointer_r <= #1 de_csr[31:4]; + end + else pointer_r <= #1 1'b0; + +always @(posedge clk) + if(CH_EN & HAVE_ED) + begin + if(this_ptr_set) pointer_sr <= #1 pointer_r; + end + else pointer_sr <= #1 1'b0; + +// --------------------------------------------------- +// CSR + +always @(posedge clk or negedge rst) + if(!rst) ch_csr_r <= #1 1'b0; + else + if(CH_EN) + begin + if(ch_csr_we) ch_csr_r <= #1 wb_rf_din[8:0]; + else + begin + if(ch_done_we) ch_csr_r[`WDMA_CH_EN] <= #1 1'b0; + if(ch_csr_dewe) ch_csr_r[4:1] <= #1 de_csr[19:16]; + end + end + +// done bit +always @(posedge clk or negedge rst) + if(!rst) ch_done <= #1 1'b0; + else + if(CH_EN) + begin + if(ch_csr_we) ch_done <= #1 !wb_rf_din[`WDMA_CH_EN]; + else + if(ch_done_we) ch_done <= #1 1'b1; + end + +// busy bit +always @(posedge clk) + ch_busy <= #1 CH_EN & (ch_sel==CH_NO) & dma_busy; + +// stop bit +always @(posedge clk) + ch_stop <= #1 CH_EN & ch_csr_we & wb_rf_din[`WDMA_STOP]; + +// error bit +always @(posedge clk or negedge rst) + if(!rst) ch_err <= #1 1'b0; + else + if(CH_EN) + begin + if(ch_err_we) ch_err <= #1 1'b1; + else + if(ch_csr_re) ch_err <= #1 1'b0; + end + +// Priority Bits +always @(posedge clk or negedge rst) + if(!rst) ch_csr_r2 <= #1 3'h0; + else + if(CH_EN & ch_csr_we) ch_csr_r2 <= #1 wb_rf_din[15:13]; + +// Restart Enable Bit (REST) +always @(posedge clk or negedge rst) + if(!rst) rest_en <= #1 1'b0; + else + if(CH_EN & ch_csr_we) rest_en <= #1 wb_rf_din[16]; + +// INT Mask +always @(posedge clk or negedge rst) + if(!rst) ch_csr_r3 <= #1 3'h0; + else + if(CH_EN & ch_csr_we) ch_csr_r3 <= #1 wb_rf_din[19:17]; + +// INT Source +always @(posedge clk or negedge rst) + if(!rst) int_src_r[2] <= #1 1'b0; + else + if(CH_EN) + begin + if(chunk_done_we) int_src_r[2] <= #1 1'b1; + else + if(ch_csr_re) int_src_r[2] <= #1 1'b0; + end + +always @(posedge clk or negedge rst) + if(!rst) int_src_r[1] <= #1 1'b0; + else + if(CH_EN) + begin + if(ch_done_we) int_src_r[1] <= #1 1'b1; + else + if(ch_csr_re) int_src_r[1] <= #1 1'b0; + end + +always @(posedge clk or negedge rst) + if(!rst) int_src_r[0] <= #1 1'b0; + else + if(CH_EN) + begin + if(ch_err_we) int_src_r[0] <= #1 1'b1; + else + if(ch_csr_re) int_src_r[0] <= #1 1'b0; + end + +// Interrupt Output +assign int = |(int_src_r & ch_csr_r3) & CH_EN; + +// --------------------------------------------------- +// TXZS +always @(posedge clk) + if(CH_EN) + begin + if(ch_txsz_we) + {ch_chk_sz_r, ch_tot_sz_r} <= #1 {wb_rf_din[26:16], wb_rf_din[11:0]}; + else + if(ch_txsz_dewe) + ch_tot_sz_r <= #1 de_txsz; + else + if(ch_rl) + {ch_chk_sz_r, ch_tot_sz_r} <= #1 ch_txsz_s; + end + +// txsz shadow register +always @(posedge clk) + if(CH_EN & HAVE_ARS) + begin + + if(ch_txsz_we) ch_txsz_s <= #1 {wb_rf_din[26:16], wb_rf_din[11:0]}; + else + if(rest_en & ch_txsz_dewe & de_fetch_descr) + ch_txsz_s[11:0] <= #1 de_txsz[11:0]; + end + +// Infinite Size indicator +always @(posedge clk) + if(CH_EN) + begin + if(ch_txsz_we) ch_sz_inf <= #1 wb_rf_din[15]; + end + +// --------------------------------------------------- +// ADR0 +always @(posedge clk) + if(CH_EN) + begin + if(ch_adr0_we) ch_adr0_r <= #1 wb_rf_din[31:2]; + else + if(ch_adr0_dewe) ch_adr0_r <= #1 de_adr0[31:2]; + else + if(ch_rl) ch_adr0_r <= #1 ch_adr0_s; + end + +// Adr0 shadow register +always @(posedge clk) + if(CH_EN & HAVE_ARS) + begin + if(ch_adr0_we) ch_adr0_s <= #1 wb_rf_din[31:2]; + else + if(rest_en & ch_adr0_dewe & de_fetch_descr) + ch_adr0_s <= #1 de_adr0[31:2]; + end + +// --------------------------------------------------- +// AM0 +always @(posedge clk or negedge rst) + if(!rst) ch_am0_r <= #1 28'hfffffff; + else + if(ch_am0_we) ch_am0_r <= #1 wb_rf_din[31:4]; + +// --------------------------------------------------- +// ADR1 +always @(posedge clk) + if(CH_EN) + begin + if(ch_adr1_we) ch_adr1_r <= #1 wb_rf_din[31:2]; + else + if(ch_adr1_dewe) ch_adr1_r <= #1 de_adr1[31:2]; + else + if(ch_rl) ch_adr1_r <= #1 ch_adr1_s; + end + +// Adr1 shadow register +always @(posedge clk) + if(CH_EN & HAVE_ARS) + begin + if(ch_adr1_we) ch_adr1_s <= #1 wb_rf_din[31:2]; + else + if(rest_en & ch_adr1_dewe & de_fetch_descr) + ch_adr1_s <= #1 de_adr1[31:2]; + end + +// --------------------------------------------------- +// AM1 +always @(posedge clk or negedge rst) + if(!rst) ch_am1_r <= #1 28'hfffffff; + else + if(ch_am1_we & CH_EN & HAVE_CBUF) ch_am1_r <= #1 wb_rf_din[31:4]; + +// --------------------------------------------------- +// Software Pointer +always @(posedge clk or negedge rst) + if(!rst) sw_pointer_r <= #1 28'h0; + else + if(sw_pointer_we & CH_EN & HAVE_CBUF) sw_pointer_r <= #1 wb_rf_din[31:4]; + +// --------------------------------------------------- +// Software Pointer Match logic + +assign cmp_adr = ch_csr[2] ? ch_adr1[30:2] : ch_adr0[30:2]; + +always @(posedge clk) + ch_dis <= #1 CH_EN & HAVE_CBUF & (sw_pointer[30:2] == cmp_adr) & sw_pointer[31]; + +endmodule + + +module wb_dma_ch_rf_dummy(clk, rst, + pointer, pointer_s, ch_csr, ch_txsz, ch_adr0, ch_adr1, + ch_am0, ch_am1, sw_pointer, ch_stop, ch_dis, int, + + wb_rf_din, wb_rf_adr, wb_rf_we, wb_rf_re, + + // DMA Registers Write Back Channel Select + ch_sel, ndnr, + + // DMA Engine Status + dma_busy, dma_err, dma_done, dma_done_all, + + // DMA Engine Reg File Update ctrl signals + de_csr, de_txsz, de_adr0, de_adr1, + de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, + de_fetch_descr, dma_rest, + ptr_set + + ); + +parameter CH_NO = 0; +parameter HAVE_ARS = 1; +parameter HAVE_ED = 1; +parameter HAVE_CBUF= 1; + +input clk, rst; + +output [31:0] pointer; +output [31:0] pointer_s; +output [31:0] ch_csr; +output [31:0] ch_txsz; +output [31:0] ch_adr0; +output [31:0] ch_adr1; +output [31:0] ch_am0; +output [31:0] ch_am1; +output [31:0] sw_pointer; +output ch_stop; +output ch_dis; +output int; + +input [31:0] wb_rf_din; +input [7:0] wb_rf_adr; +input wb_rf_we; +input wb_rf_re; + +input [4:0] ch_sel; +input ndnr; + +// DMA Engine Status +input dma_busy, dma_err, dma_done, dma_done_all; + +// DMA Engine Reg File Update ctrl signals +input [31:0] de_csr; +input [11:0] de_txsz; +input [31:0] de_adr0; +input [31:0] de_adr1; +input de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, ptr_set; +input de_fetch_descr; +input dma_rest; + +assign pointer = 32'h0; +assign pointer_s = 32'h0; +assign ch_csr = 32'h0; +assign ch_txsz = 32'h0; +assign ch_adr0 = 32'h0; +assign ch_adr1 = 32'h0; +assign ch_am0 = 32'h0; +assign ch_am1 = 32'h0; +assign sw_pointer = 32'h0; +assign ch_stop = 1'b0; +assign ch_dis = 1'b0; +assign int = 1'b0; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v new file mode 100644 index 000000000..210cb3a9b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v @@ -0,0 +1,1392 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Channel Select //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_ch_sel.v,v 1.4 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_ch_sel.v,v $ +// Revision 1.4 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.3 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.4 2001/06/14 08:52:00 rudi +// +// +// Changed arbiter module name. +// +// Revision 1.3 2001/06/13 02:26:48 rudi +// +// +// Small changes after running lint. +// +// Revision 1.2 2001/06/05 10:22:36 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:35 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_ch_sel(clk, rst, + + // DMA Request Lines + req_i, ack_o, nd_i, + + // DMA Registers Inputs + pointer0, pointer0_s, ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1, + pointer1, pointer1_s, ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1, + pointer2, pointer2_s, ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1, + pointer3, pointer3_s, ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1, + pointer4, pointer4_s, ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1, + pointer5, pointer5_s, ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1, + pointer6, pointer6_s, ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1, + pointer7, pointer7_s, ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1, + pointer8, pointer8_s, ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1, + pointer9, pointer9_s, ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1, + pointer10, pointer10_s, ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1, + pointer11, pointer11_s, ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1, + pointer12, pointer12_s, ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1, + pointer13, pointer13_s, ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1, + pointer14, pointer14_s, ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1, + pointer15, pointer15_s, ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1, + pointer16, pointer16_s, ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1, + pointer17, pointer17_s, ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1, + pointer18, pointer18_s, ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1, + pointer19, pointer19_s, ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1, + pointer20, pointer20_s, ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1, + pointer21, pointer21_s, ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1, + pointer22, pointer22_s, ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1, + pointer23, pointer23_s, ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1, + pointer24, pointer24_s, ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1, + pointer25, pointer25_s, ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1, + pointer26, pointer26_s, ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1, + pointer27, pointer27_s, ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1, + pointer28, pointer28_s, ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1, + pointer29, pointer29_s, ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1, + pointer30, pointer30_s, ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1, + + // DMA Registers Write Back Channel Select + ch_sel, ndnr, + + // DMA Engine Interface + de_start, ndr, csr, pointer, txsz, adr0, adr1, am0, am1, + pointer_s, next_ch, de_ack, dma_busy + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +// chXX_conf = { CBUF, ED, ARS, EN } +parameter [1:0] pri_sel = 2'h0; +parameter [3:0] ch0_conf = 4'h1; +parameter [3:0] ch1_conf = 4'h0; +parameter [3:0] ch2_conf = 4'h0; +parameter [3:0] ch3_conf = 4'h0; +parameter [3:0] ch4_conf = 4'h0; +parameter [3:0] ch5_conf = 4'h0; +parameter [3:0] ch6_conf = 4'h0; +parameter [3:0] ch7_conf = 4'h0; +parameter [3:0] ch8_conf = 4'h0; +parameter [3:0] ch9_conf = 4'h0; +parameter [3:0] ch10_conf = 4'h0; +parameter [3:0] ch11_conf = 4'h0; +parameter [3:0] ch12_conf = 4'h0; +parameter [3:0] ch13_conf = 4'h0; +parameter [3:0] ch14_conf = 4'h0; +parameter [3:0] ch15_conf = 4'h0; +parameter [3:0] ch16_conf = 4'h0; +parameter [3:0] ch17_conf = 4'h0; +parameter [3:0] ch18_conf = 4'h0; +parameter [3:0] ch19_conf = 4'h0; +parameter [3:0] ch20_conf = 4'h0; +parameter [3:0] ch21_conf = 4'h0; +parameter [3:0] ch22_conf = 4'h0; +parameter [3:0] ch23_conf = 4'h0; +parameter [3:0] ch24_conf = 4'h0; +parameter [3:0] ch25_conf = 4'h0; +parameter [3:0] ch26_conf = 4'h0; +parameter [3:0] ch27_conf = 4'h0; +parameter [3:0] ch28_conf = 4'h0; +parameter [3:0] ch29_conf = 4'h0; +parameter [3:0] ch30_conf = 4'h0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk, rst; + +// DMA Request Lines +input [30:0] req_i; +output [30:0] ack_o; +input [30:0] nd_i; + +// Channel Registers Inputs +input [31:0] pointer0, pointer0_s, ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1; +input [31:0] pointer1, pointer1_s, ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1; +input [31:0] pointer2, pointer2_s, ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1; +input [31:0] pointer3, pointer3_s, ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1; +input [31:0] pointer4, pointer4_s, ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1; +input [31:0] pointer5, pointer5_s, ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1; +input [31:0] pointer6, pointer6_s, ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1; +input [31:0] pointer7, pointer7_s, ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1; +input [31:0] pointer8, pointer8_s, ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1; +input [31:0] pointer9, pointer9_s, ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1; +input [31:0] pointer10, pointer10_s, ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1; +input [31:0] pointer11, pointer11_s, ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1; +input [31:0] pointer12, pointer12_s, ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1; +input [31:0] pointer13, pointer13_s, ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1; +input [31:0] pointer14, pointer14_s, ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1; +input [31:0] pointer15, pointer15_s, ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1; +input [31:0] pointer16, pointer16_s, ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1; +input [31:0] pointer17, pointer17_s, ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1; +input [31:0] pointer18, pointer18_s, ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1; +input [31:0] pointer19, pointer19_s, ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1; +input [31:0] pointer20, pointer20_s, ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1; +input [31:0] pointer21, pointer21_s, ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1; +input [31:0] pointer22, pointer22_s, ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1; +input [31:0] pointer23, pointer23_s, ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1; +input [31:0] pointer24, pointer24_s, ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1; +input [31:0] pointer25, pointer25_s, ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1; +input [31:0] pointer26, pointer26_s, ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1; +input [31:0] pointer27, pointer27_s, ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1; +input [31:0] pointer28, pointer28_s, ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1; +input [31:0] pointer29, pointer29_s, ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1; +input [31:0] pointer30, pointer30_s, ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1; + +output [4:0] ch_sel; // Write Back Channel Select +output [30:0] ndnr; // Next Descriptor No Request + +output de_start; // Start DMA Engine Indicator +output ndr; // Next Descriptor With Request (for current channel) +output [31:0] csr; // Selected Channel CSR +output [31:0] pointer; // LL Descriptor pointer +output [31:0] pointer_s; // LL Descriptor previous pointer +output [31:0] txsz; // Selected Channel Transfer Size +output [31:0] adr0, adr1; // Selected Channel Addresses +output [31:0] am0, am1; // Selected Channel Address Masks + +input next_ch; // Indicates the DMA Engine is done + // with current transfer +input de_ack; // DMA engine ack output + +input dma_busy; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [30:0] ack_o; +wire [30:0] valid; // Indicates which channel is valid +reg valid_sel; +reg [30:0] req_r; // Channel Request inputs +reg [30:0] ndr_r; // Next Descriptor Registered (and Request) +reg [30:0] ndnr; // Next Descriptor Registered (and Not Request) +wire [2:0] pri_out; // Highest unserviced priority +wire [2:0] pri0, pri1, pri2, pri3; // Channel Priorities +wire [2:0] pri4, pri5, pri6, pri7; +wire [2:0] pri8, pri9, pri10, pri11; +wire [2:0] pri12, pri13, pri14, pri15; +wire [2:0] pri16, pri17, pri18, pri19; +wire [2:0] pri20, pri21, pri22, pri23; +wire [2:0] pri24, pri25, pri26, pri27; +wire [2:0] pri28, pri29, pri30; +reg [4:0] ch_sel_d; +reg [4:0] ch_sel_r; + +reg ndr; +reg next_start; +reg de_start_r; +reg [31:0] csr; // Selected Channel CSR +reg [31:0] pointer; +reg [31:0] pointer_s; +reg [31:0] txsz; // Selected Channel Transfer Size +reg [31:0] adr0, adr1; // Selected Channel Addresses +reg [31:0] am0, am1; // Selected Channel Address Masks + + // Arbiter Request Inputs +wire [30:0] req_p0, req_p1, req_p2, req_p3; +wire [30:0] req_p4, req_p5, req_p6, req_p7; +wire [30:0] req_p8, req_p9, req_p10, req_p11; +wire [30:0] req_p12, req_p13, req_p14, req_p15; +wire [30:0] req_p16, req_p17, req_p18, req_p19; +wire [30:0] req_p20, req_p21, req_p22, req_p23; +wire [30:0] req_p24, req_p25, req_p26, req_p27; +wire [30:0] req_p28, req_p29, req_p30; + // Arbiter Grant Outputs +wire [4:0] gnt_p0_d, gnt_p1_d, gnt_p2_d, gnt_p3_d; +wire [4:0] gnt_p4_d, gnt_p5_d, gnt_p6_d, gnt_p7_d; +wire [4:0] gnt_p0, gnt_p1, gnt_p2, gnt_p3; +wire [4:0] gnt_p4, gnt_p5, gnt_p6, gnt_p7; +wire [4:0] gnt_p8, gnt_p9, gnt_p10, gnt_p11; +wire [4:0] gnt_p12, gnt_p13, gnt_p14, gnt_p15; +wire [4:0] gnt_p16, gnt_p17, gnt_p18, gnt_p19; +wire [4:0] gnt_p20, gnt_p21, gnt_p22, gnt_p23; +wire [4:0] gnt_p24, gnt_p25, gnt_p26, gnt_p27; +wire [4:0] gnt_p28, gnt_p29, gnt_p30; + + +//////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign pri0[0] = ch0_csr[13]; +assign pri0[1] = (pri_sel == 2'd0) ? 1'b0 : ch0_csr[14]; +assign pri0[2] = (pri_sel == 2'd2) ? ch0_csr[15] : 1'b0; +assign pri1[0] = ch1_csr[13]; +assign pri1[1] = (pri_sel == 2'd0) ? 1'b0 : ch1_csr[14]; +assign pri1[2] = (pri_sel == 2'd2) ? ch1_csr[15] : 1'b0; +assign pri2[0] = ch2_csr[13]; +assign pri2[1] = (pri_sel == 2'd0) ? 1'b0 : ch2_csr[14]; +assign pri2[2] = (pri_sel == 2'd2) ? ch2_csr[15] : 1'b0; +assign pri3[0] = ch3_csr[13]; +assign pri3[1] = (pri_sel == 2'd0) ? 1'b0 : ch3_csr[14]; +assign pri3[2] = (pri_sel == 2'd2) ? ch3_csr[15] : 1'b0; +assign pri4[0] = ch4_csr[13]; +assign pri4[1] = (pri_sel == 2'd0) ? 1'b0 : ch4_csr[14]; +assign pri4[2] = (pri_sel == 2'd2) ? ch4_csr[15] : 1'b0; +assign pri5[0] = ch5_csr[13]; +assign pri5[1] = (pri_sel == 2'd0) ? 1'b0 : ch5_csr[14]; +assign pri5[2] = (pri_sel == 2'd2) ? ch5_csr[15] : 1'b0; +assign pri6[0] = ch6_csr[13]; +assign pri6[1] = (pri_sel == 2'd0) ? 1'b0 : ch6_csr[14]; +assign pri6[2] = (pri_sel == 2'd2) ? ch6_csr[15] : 1'b0; +assign pri7[0] = ch7_csr[13]; +assign pri7[1] = (pri_sel == 2'd0) ? 1'b0 : ch7_csr[14]; +assign pri7[2] = (pri_sel == 2'd2) ? ch7_csr[15] : 1'b0; +assign pri8[0] = ch8_csr[13]; +assign pri8[1] = (pri_sel == 2'd0) ? 1'b0 : ch8_csr[14]; +assign pri8[2] = (pri_sel == 2'd2) ? ch8_csr[15] : 1'b0; +assign pri9[0] = ch9_csr[13]; +assign pri9[1] = (pri_sel == 2'd0) ? 1'b0 : ch9_csr[14]; +assign pri9[2] = (pri_sel == 2'd2) ? ch9_csr[15] : 1'b0; +assign pri10[0] = ch10_csr[13]; +assign pri10[1] = (pri_sel == 2'd0) ? 1'b0 : ch10_csr[14]; +assign pri10[2] = (pri_sel == 2'd2) ? ch10_csr[15] : 1'b0; +assign pri11[0] = ch11_csr[13]; +assign pri11[1] = (pri_sel == 2'd0) ? 1'b0 : ch11_csr[14]; +assign pri11[2] = (pri_sel == 2'd2) ? ch11_csr[15] : 1'b0; +assign pri12[0] = ch12_csr[13]; +assign pri12[1] = (pri_sel == 2'd0) ? 1'b0 : ch12_csr[14]; +assign pri12[2] = (pri_sel == 2'd2) ? ch12_csr[15] : 1'b0; +assign pri13[0] = ch13_csr[13]; +assign pri13[1] = (pri_sel == 2'd0) ? 1'b0 : ch13_csr[14]; +assign pri13[2] = (pri_sel == 2'd2) ? ch13_csr[15] : 1'b0; +assign pri14[0] = ch14_csr[13]; +assign pri14[1] = (pri_sel == 2'd0) ? 1'b0 : ch14_csr[14]; +assign pri14[2] = (pri_sel == 2'd2) ? ch14_csr[15] : 1'b0; +assign pri15[0] = ch15_csr[13]; +assign pri15[1] = (pri_sel == 2'd0) ? 1'b0 : ch15_csr[14]; +assign pri15[2] = (pri_sel == 2'd2) ? ch15_csr[15] : 1'b0; +assign pri16[0] = ch16_csr[13]; +assign pri16[1] = (pri_sel == 2'd0) ? 1'b0 : ch16_csr[14]; +assign pri16[2] = (pri_sel == 2'd2) ? ch16_csr[15] : 1'b0; +assign pri17[0] = ch17_csr[13]; +assign pri17[1] = (pri_sel == 2'd0) ? 1'b0 : ch17_csr[14]; +assign pri17[2] = (pri_sel == 2'd2) ? ch17_csr[15] : 1'b0; +assign pri18[0] = ch18_csr[13]; +assign pri18[1] = (pri_sel == 2'd0) ? 1'b0 : ch18_csr[14]; +assign pri18[2] = (pri_sel == 2'd2) ? ch18_csr[15] : 1'b0; +assign pri19[0] = ch19_csr[13]; +assign pri19[1] = (pri_sel == 2'd0) ? 1'b0 : ch19_csr[14]; +assign pri19[2] = (pri_sel == 2'd2) ? ch19_csr[15] : 1'b0; +assign pri20[0] = ch20_csr[13]; +assign pri20[1] = (pri_sel == 2'd0) ? 1'b0 : ch20_csr[14]; +assign pri20[2] = (pri_sel == 2'd2) ? ch20_csr[15] : 1'b0; +assign pri21[0] = ch21_csr[13]; +assign pri21[1] = (pri_sel == 2'd0) ? 1'b0 : ch21_csr[14]; +assign pri21[2] = (pri_sel == 2'd2) ? ch21_csr[15] : 1'b0; +assign pri22[0] = ch22_csr[13]; +assign pri22[1] = (pri_sel == 2'd0) ? 1'b0 : ch22_csr[14]; +assign pri22[2] = (pri_sel == 2'd2) ? ch22_csr[15] : 1'b0; +assign pri23[0] = ch23_csr[13]; +assign pri23[1] = (pri_sel == 2'd0) ? 1'b0 : ch23_csr[14]; +assign pri23[2] = (pri_sel == 2'd2) ? ch23_csr[15] : 1'b0; +assign pri24[0] = ch24_csr[13]; +assign pri24[1] = (pri_sel == 2'd0) ? 1'b0 : ch24_csr[14]; +assign pri24[2] = (pri_sel == 2'd2) ? ch24_csr[15] : 1'b0; +assign pri25[0] = ch25_csr[13]; +assign pri25[1] = (pri_sel == 2'd0) ? 1'b0 : ch25_csr[14]; +assign pri25[2] = (pri_sel == 2'd2) ? ch25_csr[15] : 1'b0; +assign pri26[0] = ch26_csr[13]; +assign pri26[1] = (pri_sel == 2'd0) ? 1'b0 : ch26_csr[14]; +assign pri26[2] = (pri_sel == 2'd2) ? ch26_csr[15] : 1'b0; +assign pri27[0] = ch27_csr[13]; +assign pri27[1] = (pri_sel == 2'd0) ? 1'b0 : ch27_csr[14]; +assign pri27[2] = (pri_sel == 2'd2) ? ch27_csr[15] : 1'b0; +assign pri28[0] = ch28_csr[13]; +assign pri28[1] = (pri_sel == 2'd0) ? 1'b0 : ch28_csr[14]; +assign pri28[2] = (pri_sel == 2'd2) ? ch28_csr[15] : 1'b0; +assign pri29[0] = ch29_csr[13]; +assign pri29[1] = (pri_sel == 2'd0) ? 1'b0 : ch29_csr[14]; +assign pri29[2] = (pri_sel == 2'd2) ? ch29_csr[15] : 1'b0; +assign pri30[0] = ch30_csr[13]; +assign pri30[1] = (pri_sel == 2'd0) ? 1'b0 : ch30_csr[14]; +assign pri30[2] = (pri_sel == 2'd2) ? ch30_csr[15] : 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// Misc logic +// + +// Chanel Valid flag +// The valid flag is asserted when the channel is enabled, +// and is either in "normal mode" (software control) or +// "hw handshake mode" (reqN control) +// validN = ch_enabled & (sw_mode | (hw_mode & reqN) ) + +always @(posedge clk) + req_r <= #1 req_i & ~ack_o; + +assign valid[0] = ch0_conf[0] & ch0_csr[`WDMA_CH_EN] & (ch0_csr[`WDMA_MODE] ? (req_r[0] & !ack_o[0]) : 1'b1); +assign valid[1] = ch1_conf[0] & ch1_csr[`WDMA_CH_EN] & (ch1_csr[`WDMA_MODE] ? (req_r[1] & !ack_o[1]) : 1'b1); +assign valid[2] = ch2_conf[0] & ch2_csr[`WDMA_CH_EN] & (ch2_csr[`WDMA_MODE] ? (req_r[2] & !ack_o[2]) : 1'b1); +assign valid[3] = ch3_conf[0] & ch3_csr[`WDMA_CH_EN] & (ch3_csr[`WDMA_MODE] ? (req_r[3] & !ack_o[3]) : 1'b1); +assign valid[4] = ch4_conf[0] & ch4_csr[`WDMA_CH_EN] & (ch4_csr[`WDMA_MODE] ? (req_r[4] & !ack_o[4]) : 1'b1); +assign valid[5] = ch5_conf[0] & ch5_csr[`WDMA_CH_EN] & (ch5_csr[`WDMA_MODE] ? (req_r[5] & !ack_o[5]) : 1'b1); +assign valid[6] = ch6_conf[0] & ch6_csr[`WDMA_CH_EN] & (ch6_csr[`WDMA_MODE] ? (req_r[6] & !ack_o[6]) : 1'b1); +assign valid[7] = ch7_conf[0] & ch7_csr[`WDMA_CH_EN] & (ch7_csr[`WDMA_MODE] ? (req_r[7] & !ack_o[7]) : 1'b1); +assign valid[8] = ch8_conf[0] & ch8_csr[`WDMA_CH_EN] & (ch8_csr[`WDMA_MODE] ? (req_r[8] & !ack_o[8]) : 1'b1); +assign valid[9] = ch9_conf[0] & ch9_csr[`WDMA_CH_EN] & (ch9_csr[`WDMA_MODE] ? (req_r[9] & !ack_o[9]) : 1'b1); +assign valid[10] = ch10_conf[0] & ch10_csr[`WDMA_CH_EN] & (ch10_csr[`WDMA_MODE] ? (req_r[10] & !ack_o[10]) : 1'b1); +assign valid[11] = ch11_conf[0] & ch11_csr[`WDMA_CH_EN] & (ch11_csr[`WDMA_MODE] ? (req_r[11] & !ack_o[11]) : 1'b1); +assign valid[12] = ch12_conf[0] & ch12_csr[`WDMA_CH_EN] & (ch12_csr[`WDMA_MODE] ? (req_r[12] & !ack_o[12]) : 1'b1); +assign valid[13] = ch13_conf[0] & ch13_csr[`WDMA_CH_EN] & (ch13_csr[`WDMA_MODE] ? (req_r[13] & !ack_o[13]) : 1'b1); +assign valid[14] = ch14_conf[0] & ch14_csr[`WDMA_CH_EN] & (ch14_csr[`WDMA_MODE] ? (req_r[14] & !ack_o[14]) : 1'b1); +assign valid[15] = ch15_conf[0] & ch15_csr[`WDMA_CH_EN] & (ch15_csr[`WDMA_MODE] ? (req_r[15] & !ack_o[15]) : 1'b1); +assign valid[16] = ch16_conf[0] & ch16_csr[`WDMA_CH_EN] & (ch16_csr[`WDMA_MODE] ? (req_r[16] & !ack_o[16]) : 1'b1); +assign valid[17] = ch17_conf[0] & ch17_csr[`WDMA_CH_EN] & (ch17_csr[`WDMA_MODE] ? (req_r[17] & !ack_o[17]) : 1'b1); +assign valid[18] = ch18_conf[0] & ch18_csr[`WDMA_CH_EN] & (ch18_csr[`WDMA_MODE] ? (req_r[18] & !ack_o[18]) : 1'b1); +assign valid[19] = ch19_conf[0] & ch19_csr[`WDMA_CH_EN] & (ch19_csr[`WDMA_MODE] ? (req_r[19] & !ack_o[19]) : 1'b1); +assign valid[20] = ch20_conf[0] & ch20_csr[`WDMA_CH_EN] & (ch20_csr[`WDMA_MODE] ? (req_r[20] & !ack_o[20]) : 1'b1); +assign valid[21] = ch21_conf[0] & ch21_csr[`WDMA_CH_EN] & (ch21_csr[`WDMA_MODE] ? (req_r[21] & !ack_o[21]) : 1'b1); +assign valid[22] = ch22_conf[0] & ch22_csr[`WDMA_CH_EN] & (ch22_csr[`WDMA_MODE] ? (req_r[22] & !ack_o[22]) : 1'b1); +assign valid[23] = ch23_conf[0] & ch23_csr[`WDMA_CH_EN] & (ch23_csr[`WDMA_MODE] ? (req_r[23] & !ack_o[23]) : 1'b1); +assign valid[24] = ch24_conf[0] & ch24_csr[`WDMA_CH_EN] & (ch24_csr[`WDMA_MODE] ? (req_r[24] & !ack_o[24]) : 1'b1); +assign valid[25] = ch25_conf[0] & ch25_csr[`WDMA_CH_EN] & (ch25_csr[`WDMA_MODE] ? (req_r[25] & !ack_o[25]) : 1'b1); +assign valid[26] = ch26_conf[0] & ch26_csr[`WDMA_CH_EN] & (ch26_csr[`WDMA_MODE] ? (req_r[26] & !ack_o[26]) : 1'b1); +assign valid[27] = ch27_conf[0] & ch27_csr[`WDMA_CH_EN] & (ch27_csr[`WDMA_MODE] ? (req_r[27] & !ack_o[27]) : 1'b1); +assign valid[28] = ch28_conf[0] & ch28_csr[`WDMA_CH_EN] & (ch28_csr[`WDMA_MODE] ? (req_r[28] & !ack_o[28]) : 1'b1); +assign valid[29] = ch29_conf[0] & ch29_csr[`WDMA_CH_EN] & (ch29_csr[`WDMA_MODE] ? (req_r[29] & !ack_o[29]) : 1'b1); +assign valid[30] = ch30_conf[0] & ch30_csr[`WDMA_CH_EN] & (ch30_csr[`WDMA_MODE] ? (req_r[30] & !ack_o[30]) : 1'b1); + +always @(posedge clk) + ndr_r <= #1 nd_i & req_i; + +always @(posedge clk) + ndnr <= #1 nd_i & ~req_i; + +// Start Signal for DMA engine +assign de_start = (valid_sel & !de_start_r ) | next_start; + +always @(posedge clk) + de_start_r <= #1 valid_sel; + +always @(posedge clk) + next_start <= #1 next_ch & valid_sel; + +// Ack outputs for HW handshake mode +always @(posedge clk) + ack_o[0] <= #1 ch0_conf[0] & (ch_sel == 5'h0) & ch0_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[1] <= #1 ch1_conf[0] & (ch_sel == 5'h1) & ch1_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[2] <= #1 ch2_conf[0] & (ch_sel == 5'h2) & ch2_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[3] <= #1 ch3_conf[0] & (ch_sel == 5'h3) & ch3_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[4] <= #1 ch4_conf[0] & (ch_sel == 5'h4) & ch4_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[5] <= #1 ch5_conf[0] & (ch_sel == 5'h5) & ch5_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[6] <= #1 ch6_conf[0] & (ch_sel == 5'h6) & ch6_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[7] <= #1 ch7_conf[0] & (ch_sel == 5'h7) & ch7_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[8] <= #1 ch8_conf[0] & (ch_sel == 5'h8) & ch8_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[9] <= #1 ch9_conf[0] & (ch_sel == 5'h9) & ch9_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[10] <= #1 ch10_conf[0] & (ch_sel == 5'ha) & ch10_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[11] <= #1 ch11_conf[0] & (ch_sel == 5'hb) & ch11_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[12] <= #1 ch12_conf[0] & (ch_sel == 5'hc) & ch12_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[13] <= #1 ch13_conf[0] & (ch_sel == 5'hd) & ch13_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[14] <= #1 ch14_conf[0] & (ch_sel == 5'he) & ch14_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[15] <= #1 ch15_conf[0] & (ch_sel == 5'hf) & ch15_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[16] <= #1 ch16_conf[0] & (ch_sel == 5'h10) & ch16_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[17] <= #1 ch17_conf[0] & (ch_sel == 5'h11) & ch17_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[18] <= #1 ch18_conf[0] & (ch_sel == 5'h12) & ch18_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[19] <= #1 ch19_conf[0] & (ch_sel == 5'h13) & ch19_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[20] <= #1 ch20_conf[0] & (ch_sel == 5'h14) & ch20_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[21] <= #1 ch21_conf[0] & (ch_sel == 5'h15) & ch21_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[22] <= #1 ch22_conf[0] & (ch_sel == 5'h16) & ch22_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[23] <= #1 ch23_conf[0] & (ch_sel == 5'h17) & ch23_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[24] <= #1 ch24_conf[0] & (ch_sel == 5'h18) & ch24_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[25] <= #1 ch25_conf[0] & (ch_sel == 5'h19) & ch25_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[26] <= #1 ch26_conf[0] & (ch_sel == 5'h1a) & ch26_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[27] <= #1 ch27_conf[0] & (ch_sel == 5'h1b) & ch27_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[28] <= #1 ch28_conf[0] & (ch_sel == 5'h1c) & ch28_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[29] <= #1 ch29_conf[0] & (ch_sel == 5'h1d) & ch29_csr[`WDMA_MODE] & de_ack; + +always @(posedge clk) + ack_o[30] <= #1 ch30_conf[0] & (ch_sel == 5'h1e) & ch30_csr[`WDMA_MODE] & de_ack; + +// Channel Select +always @(posedge clk or negedge rst) + if(!rst) ch_sel_r <= #1 0; + else + if(de_start) ch_sel_r <= #1 ch_sel_d; + +assign ch_sel = !dma_busy ? ch_sel_d : ch_sel_r; + +//////////////////////////////////////////////////////////////////// +// +// Select Registers based on arbiter (and priority) outputs +// + +always @(ch_sel or valid) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: valid_sel = valid[0]; + 5'h1: valid_sel = valid[1]; + 5'h2: valid_sel = valid[2]; + 5'h3: valid_sel = valid[3]; + 5'h4: valid_sel = valid[4]; + 5'h5: valid_sel = valid[5]; + 5'h6: valid_sel = valid[6]; + 5'h7: valid_sel = valid[7]; + 5'h8: valid_sel = valid[8]; + 5'h9: valid_sel = valid[9]; + 5'ha: valid_sel = valid[10]; + 5'hb: valid_sel = valid[11]; + 5'hc: valid_sel = valid[12]; + 5'hd: valid_sel = valid[13]; + 5'he: valid_sel = valid[14]; + 5'hf: valid_sel = valid[15]; + 5'h10: valid_sel = valid[16]; + 5'h11: valid_sel = valid[17]; + 5'h12: valid_sel = valid[18]; + 5'h13: valid_sel = valid[19]; + 5'h14: valid_sel = valid[20]; + 5'h15: valid_sel = valid[21]; + 5'h16: valid_sel = valid[22]; + 5'h17: valid_sel = valid[23]; + 5'h18: valid_sel = valid[24]; + 5'h19: valid_sel = valid[25]; + 5'h1a: valid_sel = valid[26]; + 5'h1b: valid_sel = valid[27]; + 5'h1c: valid_sel = valid[28]; + 5'h1d: valid_sel = valid[29]; + 5'h1e: valid_sel = valid[30]; + endcase + +always @(ch_sel or ndr_r) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: ndr = ndr_r[0]; + 5'h1: ndr = ndr_r[1]; + 5'h2: ndr = ndr_r[2]; + 5'h3: ndr = ndr_r[3]; + 5'h4: ndr = ndr_r[4]; + 5'h5: ndr = ndr_r[5]; + 5'h6: ndr = ndr_r[6]; + 5'h7: ndr = ndr_r[7]; + 5'h8: ndr = ndr_r[8]; + 5'h9: ndr = ndr_r[9]; + 5'ha: ndr = ndr_r[10]; + 5'hb: ndr = ndr_r[11]; + 5'hc: ndr = ndr_r[12]; + 5'hd: ndr = ndr_r[13]; + 5'he: ndr = ndr_r[14]; + 5'hf: ndr = ndr_r[15]; + 5'h10: ndr = ndr_r[16]; + 5'h11: ndr = ndr_r[17]; + 5'h12: ndr = ndr_r[18]; + 5'h13: ndr = ndr_r[19]; + 5'h14: ndr = ndr_r[20]; + 5'h15: ndr = ndr_r[21]; + 5'h16: ndr = ndr_r[22]; + 5'h17: ndr = ndr_r[23]; + 5'h18: ndr = ndr_r[24]; + 5'h19: ndr = ndr_r[25]; + 5'h1a: ndr = ndr_r[26]; + 5'h1b: ndr = ndr_r[27]; + 5'h1c: ndr = ndr_r[28]; + 5'h1d: ndr = ndr_r[29]; + 5'h1e: ndr = ndr_r[30]; + endcase + +always @(ch_sel or pointer0 or pointer1 or pointer2 or pointer3 or pointer4 + or pointer5 or pointer6 or pointer7 or pointer8 or pointer9 + or pointer10 or pointer11 or pointer12 or pointer13 or pointer14 + or pointer15 or pointer16 or pointer17 or pointer18 or pointer19 + or pointer20 or pointer21 or pointer22 or pointer23 or pointer24 + or pointer25 or pointer26 or pointer27 or pointer28 or pointer29 + or pointer30 ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: pointer = pointer0; + 5'h1: pointer = pointer1; + 5'h2: pointer = pointer2; + 5'h3: pointer = pointer3; + 5'h4: pointer = pointer4; + 5'h5: pointer = pointer5; + 5'h6: pointer = pointer6; + 5'h7: pointer = pointer7; + 5'h8: pointer = pointer8; + 5'h9: pointer = pointer9; + 5'ha: pointer = pointer10; + 5'hb: pointer = pointer11; + 5'hc: pointer = pointer12; + 5'hd: pointer = pointer13; + 5'he: pointer = pointer14; + 5'hf: pointer = pointer15; + 5'h10: pointer = pointer16; + 5'h11: pointer = pointer17; + 5'h12: pointer = pointer18; + 5'h13: pointer = pointer19; + 5'h14: pointer = pointer20; + 5'h15: pointer = pointer21; + 5'h16: pointer = pointer22; + 5'h17: pointer = pointer23; + 5'h18: pointer = pointer24; + 5'h19: pointer = pointer25; + 5'h1a: pointer = pointer26; + 5'h1b: pointer = pointer27; + 5'h1c: pointer = pointer28; + 5'h1d: pointer = pointer29; + 5'h1e: pointer = pointer30; + endcase + +always @(ch_sel or pointer0_s or pointer1_s or pointer2_s or pointer3_s or pointer4_s + or pointer5_s or pointer6_s or pointer7_s or pointer8_s or pointer9_s + or pointer10_s or pointer11_s or pointer12_s or pointer13_s or pointer14_s + or pointer15_s or pointer16_s or pointer17_s or pointer18_s or pointer19_s + or pointer20_s or pointer21_s or pointer22_s or pointer23_s or pointer24_s + or pointer25_s or pointer26_s or pointer27_s or pointer28_s or pointer29_s + or pointer30_s ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: pointer_s = pointer0_s; + 5'h1: pointer_s = pointer1_s; + 5'h2: pointer_s = pointer2_s; + 5'h3: pointer_s = pointer3_s; + 5'h4: pointer_s = pointer4_s; + 5'h5: pointer_s = pointer5_s; + 5'h6: pointer_s = pointer6_s; + 5'h7: pointer_s = pointer7_s; + 5'h8: pointer_s = pointer8_s; + 5'h9: pointer_s = pointer9_s; + 5'ha: pointer_s = pointer10_s; + 5'hb: pointer_s = pointer11_s; + 5'hc: pointer_s = pointer12_s; + 5'hd: pointer_s = pointer13_s; + 5'he: pointer_s = pointer14_s; + 5'hf: pointer_s = pointer15_s; + 5'h10: pointer_s = pointer16_s; + 5'h11: pointer_s = pointer17_s; + 5'h12: pointer_s = pointer18_s; + 5'h13: pointer_s = pointer19_s; + 5'h14: pointer_s = pointer20_s; + 5'h15: pointer_s = pointer21_s; + 5'h16: pointer_s = pointer22_s; + 5'h17: pointer_s = pointer23_s; + 5'h18: pointer_s = pointer24_s; + 5'h19: pointer_s = pointer25_s; + 5'h1a: pointer_s = pointer26_s; + 5'h1b: pointer_s = pointer27_s; + 5'h1c: pointer_s = pointer28_s; + 5'h1d: pointer_s = pointer29_s; + 5'h1e: pointer_s = pointer30_s; + endcase + +always @(ch_sel or ch0_csr or ch1_csr or ch2_csr or ch3_csr or ch4_csr + or ch5_csr or ch6_csr or ch7_csr or ch8_csr or ch9_csr + or ch10_csr or ch11_csr or ch12_csr or ch13_csr or ch14_csr + or ch15_csr or ch16_csr or ch17_csr or ch18_csr or ch19_csr + or ch20_csr or ch21_csr or ch22_csr or ch23_csr or ch24_csr + or ch25_csr or ch26_csr or ch27_csr or ch28_csr or ch29_csr + or ch30_csr ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: csr = ch0_csr; + 5'h1: csr = ch1_csr; + 5'h2: csr = ch2_csr; + 5'h3: csr = ch3_csr; + 5'h4: csr = ch4_csr; + 5'h5: csr = ch5_csr; + 5'h6: csr = ch6_csr; + 5'h7: csr = ch7_csr; + 5'h8: csr = ch8_csr; + 5'h9: csr = ch9_csr; + 5'ha: csr = ch10_csr; + 5'hb: csr = ch11_csr; + 5'hc: csr = ch12_csr; + 5'hd: csr = ch13_csr; + 5'he: csr = ch14_csr; + 5'hf: csr = ch15_csr; + 5'h10: csr = ch16_csr; + 5'h11: csr = ch17_csr; + 5'h12: csr = ch18_csr; + 5'h13: csr = ch19_csr; + 5'h14: csr = ch20_csr; + 5'h15: csr = ch21_csr; + 5'h16: csr = ch22_csr; + 5'h17: csr = ch23_csr; + 5'h18: csr = ch24_csr; + 5'h19: csr = ch25_csr; + 5'h1a: csr = ch26_csr; + 5'h1b: csr = ch27_csr; + 5'h1c: csr = ch28_csr; + 5'h1d: csr = ch29_csr; + 5'h1e: csr = ch30_csr; + endcase + +always @(ch_sel or ch0_txsz or ch1_txsz or ch2_txsz or ch3_txsz or ch4_txsz + or ch5_txsz or ch6_txsz or ch7_txsz or ch8_txsz or ch9_txsz + or ch10_txsz or ch11_txsz or ch12_txsz or ch13_txsz or ch14_txsz + or ch15_txsz or ch16_txsz or ch17_txsz or ch18_txsz or ch19_txsz + or ch20_txsz or ch21_txsz or ch22_txsz or ch23_txsz or ch24_txsz + or ch25_txsz or ch26_txsz or ch27_txsz or ch28_txsz or ch29_txsz + or ch30_txsz ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: txsz = ch0_txsz; + 5'h1: txsz = ch1_txsz; + 5'h2: txsz = ch2_txsz; + 5'h3: txsz = ch3_txsz; + 5'h4: txsz = ch4_txsz; + 5'h5: txsz = ch5_txsz; + 5'h6: txsz = ch6_txsz; + 5'h7: txsz = ch7_txsz; + 5'h8: txsz = ch8_txsz; + 5'h9: txsz = ch9_txsz; + 5'ha: txsz = ch10_txsz; + 5'hb: txsz = ch11_txsz; + 5'hc: txsz = ch12_txsz; + 5'hd: txsz = ch13_txsz; + 5'he: txsz = ch14_txsz; + 5'hf: txsz = ch15_txsz; + 5'h10: txsz = ch16_txsz; + 5'h11: txsz = ch17_txsz; + 5'h12: txsz = ch18_txsz; + 5'h13: txsz = ch19_txsz; + 5'h14: txsz = ch20_txsz; + 5'h15: txsz = ch21_txsz; + 5'h16: txsz = ch22_txsz; + 5'h17: txsz = ch23_txsz; + 5'h18: txsz = ch24_txsz; + 5'h19: txsz = ch25_txsz; + 5'h1a: txsz = ch26_txsz; + 5'h1b: txsz = ch27_txsz; + 5'h1c: txsz = ch28_txsz; + 5'h1d: txsz = ch29_txsz; + 5'h1e: txsz = ch30_txsz; + endcase + +always @(ch_sel or ch0_adr0 or ch1_adr0 or ch2_adr0 or ch3_adr0 or ch4_adr0 + or ch5_adr0 or ch6_adr0 or ch7_adr0 or ch8_adr0 or ch9_adr0 + or ch10_adr0 or ch11_adr0 or ch12_adr0 or ch13_adr0 or ch14_adr0 + or ch15_adr0 or ch16_adr0 or ch17_adr0 or ch18_adr0 or ch19_adr0 + or ch20_adr0 or ch21_adr0 or ch22_adr0 or ch23_adr0 or ch24_adr0 + or ch25_adr0 or ch26_adr0 or ch27_adr0 or ch28_adr0 or ch29_adr0 + or ch30_adr0 ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: adr0 = ch0_adr0; + 5'h1: adr0 = ch1_adr0; + 5'h2: adr0 = ch2_adr0; + 5'h3: adr0 = ch3_adr0; + 5'h4: adr0 = ch4_adr0; + 5'h5: adr0 = ch5_adr0; + 5'h6: adr0 = ch6_adr0; + 5'h7: adr0 = ch7_adr0; + 5'h8: adr0 = ch8_adr0; + 5'h9: adr0 = ch9_adr0; + 5'ha: adr0 = ch10_adr0; + 5'hb: adr0 = ch11_adr0; + 5'hc: adr0 = ch12_adr0; + 5'hd: adr0 = ch13_adr0; + 5'he: adr0 = ch14_adr0; + 5'hf: adr0 = ch15_adr0; + 5'h10: adr0 = ch16_adr0; + 5'h11: adr0 = ch17_adr0; + 5'h12: adr0 = ch18_adr0; + 5'h13: adr0 = ch19_adr0; + 5'h14: adr0 = ch20_adr0; + 5'h15: adr0 = ch21_adr0; + 5'h16: adr0 = ch22_adr0; + 5'h17: adr0 = ch23_adr0; + 5'h18: adr0 = ch24_adr0; + 5'h19: adr0 = ch25_adr0; + 5'h1a: adr0 = ch26_adr0; + 5'h1b: adr0 = ch27_adr0; + 5'h1c: adr0 = ch28_adr0; + 5'h1d: adr0 = ch29_adr0; + 5'h1e: adr0 = ch30_adr0; + endcase + +always @(ch_sel or ch0_adr1 or ch1_adr1 or ch2_adr1 or ch3_adr1 or ch4_adr1 + or ch5_adr1 or ch6_adr1 or ch7_adr1 or ch8_adr1 or ch9_adr1 + or ch10_adr1 or ch11_adr1 or ch12_adr1 or ch13_adr1 or ch14_adr1 + or ch15_adr1 or ch16_adr1 or ch17_adr1 or ch18_adr1 or ch19_adr1 + or ch20_adr1 or ch21_adr1 or ch22_adr1 or ch23_adr1 or ch24_adr1 + or ch25_adr1 or ch26_adr1 or ch27_adr1 or ch28_adr1 or ch29_adr1 + or ch30_adr1 ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: adr1 = ch0_adr1; + 5'h1: adr1 = ch1_adr1; + 5'h2: adr1 = ch2_adr1; + 5'h3: adr1 = ch3_adr1; + 5'h4: adr1 = ch4_adr1; + 5'h5: adr1 = ch5_adr1; + 5'h6: adr1 = ch6_adr1; + 5'h7: adr1 = ch7_adr1; + 5'h8: adr1 = ch8_adr1; + 5'h9: adr1 = ch9_adr1; + 5'ha: adr1 = ch10_adr1; + 5'hb: adr1 = ch11_adr1; + 5'hc: adr1 = ch12_adr1; + 5'hd: adr1 = ch13_adr1; + 5'he: adr1 = ch14_adr1; + 5'hf: adr1 = ch15_adr1; + 5'h10: adr1 = ch16_adr1; + 5'h11: adr1 = ch17_adr1; + 5'h12: adr1 = ch18_adr1; + 5'h13: adr1 = ch19_adr1; + 5'h14: adr1 = ch20_adr1; + 5'h15: adr1 = ch21_adr1; + 5'h16: adr1 = ch22_adr1; + 5'h17: adr1 = ch23_adr1; + 5'h18: adr1 = ch24_adr1; + 5'h19: adr1 = ch25_adr1; + 5'h1a: adr1 = ch26_adr1; + 5'h1b: adr1 = ch27_adr1; + 5'h1c: adr1 = ch28_adr1; + 5'h1d: adr1 = ch29_adr1; + 5'h1e: adr1 = ch30_adr1; + endcase + +always @(ch_sel or ch0_am0 or ch1_am0 or ch2_am0 or ch3_am0 or ch4_am0 + or ch5_am0 or ch6_am0 or ch7_am0 or ch8_am0 or ch9_am0 + or ch10_am0 or ch11_am0 or ch12_am0 or ch13_am0 or ch14_am0 + or ch15_am0 or ch16_am0 or ch17_am0 or ch18_am0 or ch19_am0 + or ch20_am0 or ch21_am0 or ch22_am0 or ch23_am0 or ch24_am0 + or ch25_am0 or ch26_am0 or ch27_am0 or ch28_am0 or ch29_am0 + or ch30_am0 ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: am0 = ch0_am0; + 5'h1: am0 = ch1_am0; + 5'h2: am0 = ch2_am0; + 5'h3: am0 = ch3_am0; + 5'h4: am0 = ch4_am0; + 5'h5: am0 = ch5_am0; + 5'h6: am0 = ch6_am0; + 5'h7: am0 = ch7_am0; + 5'h8: am0 = ch8_am0; + 5'h9: am0 = ch9_am0; + 5'ha: am0 = ch10_am0; + 5'hb: am0 = ch11_am0; + 5'hc: am0 = ch12_am0; + 5'hd: am0 = ch13_am0; + 5'he: am0 = ch14_am0; + 5'hf: am0 = ch15_am0; + 5'h10: am0 = ch16_am0; + 5'h11: am0 = ch17_am0; + 5'h12: am0 = ch18_am0; + 5'h13: am0 = ch19_am0; + 5'h14: am0 = ch20_am0; + 5'h15: am0 = ch21_am0; + 5'h16: am0 = ch22_am0; + 5'h17: am0 = ch23_am0; + 5'h18: am0 = ch24_am0; + 5'h19: am0 = ch25_am0; + 5'h1a: am0 = ch26_am0; + 5'h1b: am0 = ch27_am0; + 5'h1c: am0 = ch28_am0; + 5'h1d: am0 = ch29_am0; + 5'h1e: am0 = ch30_am0; + endcase + +always @(ch_sel or ch0_am1 or ch1_am1 or ch2_am1 or ch3_am1 or ch4_am1 + or ch5_am1 or ch6_am1 or ch7_am1 or ch8_am1 or ch9_am1 + or ch10_am1 or ch11_am1 or ch12_am1 or ch13_am1 or ch14_am1 + or ch15_am1 or ch16_am1 or ch17_am1 or ch18_am1 or ch19_am1 + or ch20_am1 or ch21_am1 or ch22_am1 or ch23_am1 or ch24_am1 + or ch25_am1 or ch26_am1 or ch27_am1 or ch28_am1 or ch29_am1 + or ch30_am1 ) + case(ch_sel) // synopsys parallel_case full_case + 5'h0: am1 = ch0_am1; + 5'h1: am1 = ch1_am1; + 5'h2: am1 = ch2_am1; + 5'h3: am1 = ch3_am1; + 5'h4: am1 = ch4_am1; + 5'h5: am1 = ch5_am1; + 5'h6: am1 = ch6_am1; + 5'h7: am1 = ch7_am1; + 5'h8: am1 = ch8_am1; + 5'h9: am1 = ch9_am1; + 5'ha: am1 = ch10_am1; + 5'hb: am1 = ch11_am1; + 5'hc: am1 = ch12_am1; + 5'hd: am1 = ch13_am1; + 5'he: am1 = ch14_am1; + 5'hf: am1 = ch15_am1; + 5'h10: am1 = ch16_am1; + 5'h11: am1 = ch17_am1; + 5'h12: am1 = ch18_am1; + 5'h13: am1 = ch19_am1; + 5'h14: am1 = ch20_am1; + 5'h15: am1 = ch21_am1; + 5'h16: am1 = ch22_am1; + 5'h17: am1 = ch23_am1; + 5'h18: am1 = ch24_am1; + 5'h19: am1 = ch25_am1; + 5'h1a: am1 = ch26_am1; + 5'h1b: am1 = ch27_am1; + 5'h1c: am1 = ch28_am1; + 5'h1d: am1 = ch29_am1; + 5'h1e: am1 = ch30_am1; + endcase + +//////////////////////////////////////////////////////////////////// +// +// Actual Chanel Arbiter and Priority Encoder +// + +// Select the arbiter for current highest priority +always @(pri_out or gnt_p0 or gnt_p1 or gnt_p2 or gnt_p3 or gnt_p4 + or gnt_p5 or gnt_p6 or gnt_p7 ) + case(pri_out) // synopsys parallel_case full_case + 3'h0: ch_sel_d = gnt_p0; + 3'h1: ch_sel_d = gnt_p1; + 3'h2: ch_sel_d = gnt_p2; + 3'h3: ch_sel_d = gnt_p3; + 3'h4: ch_sel_d = gnt_p4; + 3'h5: ch_sel_d = gnt_p5; + 3'h6: ch_sel_d = gnt_p6; + 3'h7: ch_sel_d = gnt_p7; + endcase + + +// Priority Encoder +wb_dma_ch_pri_enc + #( pri_sel, + ch0_conf, + ch1_conf, + ch2_conf, + ch3_conf, + ch4_conf, + ch5_conf, + ch6_conf, + ch7_conf, + ch8_conf, + ch9_conf, + ch10_conf, + ch11_conf, + ch12_conf, + ch13_conf, + ch14_conf, + ch15_conf, + ch16_conf, + ch17_conf, + ch18_conf, + ch19_conf, + ch20_conf, + ch21_conf, + ch22_conf, + ch23_conf, + ch24_conf, + ch25_conf, + ch26_conf, + ch27_conf, + ch28_conf, + ch29_conf, + ch30_conf) + u0( + .clk( clk ), + .valid( valid ), + .pri0( pri0 ), + .pri1( pri1 ), + .pri2( pri2 ), + .pri3( pri3 ), + .pri4( pri4 ), + .pri5( pri5 ), + .pri6( pri6 ), + .pri7( pri7 ), + .pri8( pri8 ), + .pri9( pri9 ), + .pri10( pri10 ), + .pri11( pri11 ), + .pri12( pri12 ), + .pri13( pri13 ), + .pri14( pri14 ), + .pri15( pri15 ), + .pri16( pri16 ), + .pri17( pri17 ), + .pri18( pri18 ), + .pri19( pri19 ), + .pri20( pri20 ), + .pri21( pri21 ), + .pri22( pri22 ), + .pri23( pri23 ), + .pri24( pri24 ), + .pri25( pri25 ), + .pri26( pri26 ), + .pri27( pri27 ), + .pri28( pri28 ), + .pri29( pri29 ), + .pri30( pri30 ), + .pri_out( pri_out ) + ); + +// Arbiter request lines +// Generate request depending on priority and valid bits + +assign req_p0[0] = valid[0] & (pri0==3'h0); +assign req_p0[1] = valid[1] & (pri1==3'h0); +assign req_p0[2] = valid[2] & (pri2==3'h0); +assign req_p0[3] = valid[3] & (pri3==3'h0); +assign req_p0[4] = valid[4] & (pri4==3'h0); +assign req_p0[5] = valid[5] & (pri5==3'h0); +assign req_p0[6] = valid[6] & (pri6==3'h0); +assign req_p0[7] = valid[7] & (pri7==3'h0); +assign req_p0[8] = valid[8] & (pri8==3'h0); +assign req_p0[9] = valid[9] & (pri9==3'h0); +assign req_p0[10] = valid[10] & (pri10==3'h0); +assign req_p0[11] = valid[11] & (pri11==3'h0); +assign req_p0[12] = valid[12] & (pri12==3'h0); +assign req_p0[13] = valid[13] & (pri13==3'h0); +assign req_p0[14] = valid[14] & (pri14==3'h0); +assign req_p0[15] = valid[15] & (pri15==3'h0); +assign req_p0[16] = valid[16] & (pri16==3'h0); +assign req_p0[17] = valid[17] & (pri17==3'h0); +assign req_p0[18] = valid[18] & (pri18==3'h0); +assign req_p0[19] = valid[19] & (pri19==3'h0); +assign req_p0[20] = valid[20] & (pri20==3'h0); +assign req_p0[21] = valid[21] & (pri21==3'h0); +assign req_p0[22] = valid[22] & (pri22==3'h0); +assign req_p0[23] = valid[23] & (pri23==3'h0); +assign req_p0[24] = valid[24] & (pri24==3'h0); +assign req_p0[25] = valid[25] & (pri25==3'h0); +assign req_p0[26] = valid[26] & (pri26==3'h0); +assign req_p0[27] = valid[27] & (pri27==3'h0); +assign req_p0[28] = valid[28] & (pri28==3'h0); +assign req_p0[29] = valid[29] & (pri29==3'h0); +assign req_p0[30] = valid[30] & (pri30==3'h0); + +assign req_p1[0] = valid[0] & (pri0==3'h1); +assign req_p1[1] = valid[1] & (pri1==3'h1); +assign req_p1[2] = valid[2] & (pri2==3'h1); +assign req_p1[3] = valid[3] & (pri3==3'h1); +assign req_p1[4] = valid[4] & (pri4==3'h1); +assign req_p1[5] = valid[5] & (pri5==3'h1); +assign req_p1[6] = valid[6] & (pri6==3'h1); +assign req_p1[7] = valid[7] & (pri7==3'h1); +assign req_p1[8] = valid[8] & (pri8==3'h1); +assign req_p1[9] = valid[9] & (pri9==3'h1); +assign req_p1[10] = valid[10] & (pri10==3'h1); +assign req_p1[11] = valid[11] & (pri11==3'h1); +assign req_p1[12] = valid[12] & (pri12==3'h1); +assign req_p1[13] = valid[13] & (pri13==3'h1); +assign req_p1[14] = valid[14] & (pri14==3'h1); +assign req_p1[15] = valid[15] & (pri15==3'h1); +assign req_p1[16] = valid[16] & (pri16==3'h1); +assign req_p1[17] = valid[17] & (pri17==3'h1); +assign req_p1[18] = valid[18] & (pri18==3'h1); +assign req_p1[19] = valid[19] & (pri19==3'h1); +assign req_p1[20] = valid[20] & (pri20==3'h1); +assign req_p1[21] = valid[21] & (pri21==3'h1); +assign req_p1[22] = valid[22] & (pri22==3'h1); +assign req_p1[23] = valid[23] & (pri23==3'h1); +assign req_p1[24] = valid[24] & (pri24==3'h1); +assign req_p1[25] = valid[25] & (pri25==3'h1); +assign req_p1[26] = valid[26] & (pri26==3'h1); +assign req_p1[27] = valid[27] & (pri27==3'h1); +assign req_p1[28] = valid[28] & (pri28==3'h1); +assign req_p1[29] = valid[29] & (pri29==3'h1); +assign req_p1[30] = valid[30] & (pri30==3'h1); + +assign req_p2[0] = valid[0] & (pri0==3'h2); +assign req_p2[1] = valid[1] & (pri1==3'h2); +assign req_p2[2] = valid[2] & (pri2==3'h2); +assign req_p2[3] = valid[3] & (pri3==3'h2); +assign req_p2[4] = valid[4] & (pri4==3'h2); +assign req_p2[5] = valid[5] & (pri5==3'h2); +assign req_p2[6] = valid[6] & (pri6==3'h2); +assign req_p2[7] = valid[7] & (pri7==3'h2); +assign req_p2[8] = valid[8] & (pri8==3'h2); +assign req_p2[9] = valid[9] & (pri9==3'h2); +assign req_p2[10] = valid[10] & (pri10==3'h2); +assign req_p2[11] = valid[11] & (pri11==3'h2); +assign req_p2[12] = valid[12] & (pri12==3'h2); +assign req_p2[13] = valid[13] & (pri13==3'h2); +assign req_p2[14] = valid[14] & (pri14==3'h2); +assign req_p2[15] = valid[15] & (pri15==3'h2); +assign req_p2[16] = valid[16] & (pri16==3'h2); +assign req_p2[17] = valid[17] & (pri17==3'h2); +assign req_p2[18] = valid[18] & (pri18==3'h2); +assign req_p2[19] = valid[19] & (pri19==3'h2); +assign req_p2[20] = valid[20] & (pri20==3'h2); +assign req_p2[21] = valid[21] & (pri21==3'h2); +assign req_p2[22] = valid[22] & (pri22==3'h2); +assign req_p2[23] = valid[23] & (pri23==3'h2); +assign req_p2[24] = valid[24] & (pri24==3'h2); +assign req_p2[25] = valid[25] & (pri25==3'h2); +assign req_p2[26] = valid[26] & (pri26==3'h2); +assign req_p2[27] = valid[27] & (pri27==3'h2); +assign req_p2[28] = valid[28] & (pri28==3'h2); +assign req_p2[29] = valid[29] & (pri29==3'h2); +assign req_p2[30] = valid[30] & (pri30==3'h2); + +assign req_p3[0] = valid[0] & (pri0==3'h3); +assign req_p3[1] = valid[1] & (pri1==3'h3); +assign req_p3[2] = valid[2] & (pri2==3'h3); +assign req_p3[3] = valid[3] & (pri3==3'h3); +assign req_p3[4] = valid[4] & (pri4==3'h3); +assign req_p3[5] = valid[5] & (pri5==3'h3); +assign req_p3[6] = valid[6] & (pri6==3'h3); +assign req_p3[7] = valid[7] & (pri7==3'h3); +assign req_p3[8] = valid[8] & (pri8==3'h3); +assign req_p3[9] = valid[9] & (pri9==3'h3); +assign req_p3[10] = valid[10] & (pri10==3'h3); +assign req_p3[11] = valid[11] & (pri11==3'h3); +assign req_p3[12] = valid[12] & (pri12==3'h3); +assign req_p3[13] = valid[13] & (pri13==3'h3); +assign req_p3[14] = valid[14] & (pri14==3'h3); +assign req_p3[15] = valid[15] & (pri15==3'h3); +assign req_p3[16] = valid[16] & (pri16==3'h3); +assign req_p3[17] = valid[17] & (pri17==3'h3); +assign req_p3[18] = valid[18] & (pri18==3'h3); +assign req_p3[19] = valid[19] & (pri19==3'h3); +assign req_p3[20] = valid[20] & (pri20==3'h3); +assign req_p3[21] = valid[21] & (pri21==3'h3); +assign req_p3[22] = valid[22] & (pri22==3'h3); +assign req_p3[23] = valid[23] & (pri23==3'h3); +assign req_p3[24] = valid[24] & (pri24==3'h3); +assign req_p3[25] = valid[25] & (pri25==3'h3); +assign req_p3[26] = valid[26] & (pri26==3'h3); +assign req_p3[27] = valid[27] & (pri27==3'h3); +assign req_p3[28] = valid[28] & (pri28==3'h3); +assign req_p3[29] = valid[29] & (pri29==3'h3); +assign req_p3[30] = valid[30] & (pri30==3'h3); + +assign req_p4[0] = valid[0] & (pri0==3'h4); +assign req_p4[1] = valid[1] & (pri1==3'h4); +assign req_p4[2] = valid[2] & (pri2==3'h4); +assign req_p4[3] = valid[3] & (pri3==3'h4); +assign req_p4[4] = valid[4] & (pri4==3'h4); +assign req_p4[5] = valid[5] & (pri5==3'h4); +assign req_p4[6] = valid[6] & (pri6==3'h4); +assign req_p4[7] = valid[7] & (pri7==3'h4); +assign req_p4[8] = valid[8] & (pri8==3'h4); +assign req_p4[9] = valid[9] & (pri9==3'h4); +assign req_p4[10] = valid[10] & (pri10==3'h4); +assign req_p4[11] = valid[11] & (pri11==3'h4); +assign req_p4[12] = valid[12] & (pri12==3'h4); +assign req_p4[13] = valid[13] & (pri13==3'h4); +assign req_p4[14] = valid[14] & (pri14==3'h4); +assign req_p4[15] = valid[15] & (pri15==3'h4); +assign req_p4[16] = valid[16] & (pri16==3'h4); +assign req_p4[17] = valid[17] & (pri17==3'h4); +assign req_p4[18] = valid[18] & (pri18==3'h4); +assign req_p4[19] = valid[19] & (pri19==3'h4); +assign req_p4[20] = valid[20] & (pri20==3'h4); +assign req_p4[21] = valid[21] & (pri21==3'h4); +assign req_p4[22] = valid[22] & (pri22==3'h4); +assign req_p4[23] = valid[23] & (pri23==3'h4); +assign req_p4[24] = valid[24] & (pri24==3'h4); +assign req_p4[25] = valid[25] & (pri25==3'h4); +assign req_p4[26] = valid[26] & (pri26==3'h4); +assign req_p4[27] = valid[27] & (pri27==3'h4); +assign req_p4[28] = valid[28] & (pri28==3'h4); +assign req_p4[29] = valid[29] & (pri29==3'h4); +assign req_p4[30] = valid[30] & (pri30==3'h4); + +assign req_p5[0] = valid[0] & (pri0==3'h5); +assign req_p5[1] = valid[1] & (pri1==3'h5); +assign req_p5[2] = valid[2] & (pri2==3'h5); +assign req_p5[3] = valid[3] & (pri3==3'h5); +assign req_p5[4] = valid[4] & (pri4==3'h5); +assign req_p5[5] = valid[5] & (pri5==3'h5); +assign req_p5[6] = valid[6] & (pri6==3'h5); +assign req_p5[7] = valid[7] & (pri7==3'h5); +assign req_p5[8] = valid[8] & (pri8==3'h5); +assign req_p5[9] = valid[9] & (pri9==3'h5); +assign req_p5[10] = valid[10] & (pri10==3'h5); +assign req_p5[11] = valid[11] & (pri11==3'h5); +assign req_p5[12] = valid[12] & (pri12==3'h5); +assign req_p5[13] = valid[13] & (pri13==3'h5); +assign req_p5[14] = valid[14] & (pri14==3'h5); +assign req_p5[15] = valid[15] & (pri15==3'h5); +assign req_p5[16] = valid[16] & (pri16==3'h5); +assign req_p5[17] = valid[17] & (pri17==3'h5); +assign req_p5[18] = valid[18] & (pri18==3'h5); +assign req_p5[19] = valid[19] & (pri19==3'h5); +assign req_p5[20] = valid[20] & (pri20==3'h5); +assign req_p5[21] = valid[21] & (pri21==3'h5); +assign req_p5[22] = valid[22] & (pri22==3'h5); +assign req_p5[23] = valid[23] & (pri23==3'h5); +assign req_p5[24] = valid[24] & (pri24==3'h5); +assign req_p5[25] = valid[25] & (pri25==3'h5); +assign req_p5[26] = valid[26] & (pri26==3'h5); +assign req_p5[27] = valid[27] & (pri27==3'h5); +assign req_p5[28] = valid[28] & (pri28==3'h5); +assign req_p5[29] = valid[29] & (pri29==3'h5); +assign req_p5[30] = valid[30] & (pri30==3'h5); + +assign req_p6[0] = valid[0] & (pri0==3'h6); +assign req_p6[1] = valid[1] & (pri1==3'h6); +assign req_p6[2] = valid[2] & (pri2==3'h6); +assign req_p6[3] = valid[3] & (pri3==3'h6); +assign req_p6[4] = valid[4] & (pri4==3'h6); +assign req_p6[5] = valid[5] & (pri5==3'h6); +assign req_p6[6] = valid[6] & (pri6==3'h6); +assign req_p6[7] = valid[7] & (pri7==3'h6); +assign req_p6[8] = valid[8] & (pri8==3'h6); +assign req_p6[9] = valid[9] & (pri9==3'h6); +assign req_p6[10] = valid[10] & (pri10==3'h6); +assign req_p6[11] = valid[11] & (pri11==3'h6); +assign req_p6[12] = valid[12] & (pri12==3'h6); +assign req_p6[13] = valid[13] & (pri13==3'h6); +assign req_p6[14] = valid[14] & (pri14==3'h6); +assign req_p6[15] = valid[15] & (pri15==3'h6); +assign req_p6[16] = valid[16] & (pri16==3'h6); +assign req_p6[17] = valid[17] & (pri17==3'h6); +assign req_p6[18] = valid[18] & (pri18==3'h6); +assign req_p6[19] = valid[19] & (pri19==3'h6); +assign req_p6[20] = valid[20] & (pri20==3'h6); +assign req_p6[21] = valid[21] & (pri21==3'h6); +assign req_p6[22] = valid[22] & (pri22==3'h6); +assign req_p6[23] = valid[23] & (pri23==3'h6); +assign req_p6[24] = valid[24] & (pri24==3'h6); +assign req_p6[25] = valid[25] & (pri25==3'h6); +assign req_p6[26] = valid[26] & (pri26==3'h6); +assign req_p6[27] = valid[27] & (pri27==3'h6); +assign req_p6[28] = valid[28] & (pri28==3'h6); +assign req_p6[29] = valid[29] & (pri29==3'h6); +assign req_p6[30] = valid[30] & (pri30==3'h6); + +assign req_p7[0] = valid[0] & (pri0==3'h7); +assign req_p7[1] = valid[1] & (pri1==3'h7); +assign req_p7[2] = valid[2] & (pri2==3'h7); +assign req_p7[3] = valid[3] & (pri3==3'h7); +assign req_p7[4] = valid[4] & (pri4==3'h7); +assign req_p7[5] = valid[5] & (pri5==3'h7); +assign req_p7[6] = valid[6] & (pri6==3'h7); +assign req_p7[7] = valid[7] & (pri7==3'h7); +assign req_p7[8] = valid[8] & (pri8==3'h7); +assign req_p7[9] = valid[9] & (pri9==3'h7); +assign req_p7[10] = valid[10] & (pri10==3'h7); +assign req_p7[11] = valid[11] & (pri11==3'h7); +assign req_p7[12] = valid[12] & (pri12==3'h7); +assign req_p7[13] = valid[13] & (pri13==3'h7); +assign req_p7[14] = valid[14] & (pri14==3'h7); +assign req_p7[15] = valid[15] & (pri15==3'h7); +assign req_p7[16] = valid[16] & (pri16==3'h7); +assign req_p7[17] = valid[17] & (pri17==3'h7); +assign req_p7[18] = valid[18] & (pri18==3'h7); +assign req_p7[19] = valid[19] & (pri19==3'h7); +assign req_p7[20] = valid[20] & (pri20==3'h7); +assign req_p7[21] = valid[21] & (pri21==3'h7); +assign req_p7[22] = valid[22] & (pri22==3'h7); +assign req_p7[23] = valid[23] & (pri23==3'h7); +assign req_p7[24] = valid[24] & (pri24==3'h7); +assign req_p7[25] = valid[25] & (pri25==3'h7); +assign req_p7[26] = valid[26] & (pri26==3'h7); +assign req_p7[27] = valid[27] & (pri27==3'h7); +assign req_p7[28] = valid[28] & (pri28==3'h7); +assign req_p7[29] = valid[29] & (pri29==3'h7); +assign req_p7[30] = valid[30] & (pri30==3'h7); + +// RR Arbiter for priority 0 +wb_dma_ch_arb u1( + .clk( clk ), + .rst( rst ), + .req( req_p0 ), + .gnt( gnt_p0_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 1 +wb_dma_ch_arb u2( + .clk( clk ), + .rst( rst ), + .req( req_p1 ), + .gnt( gnt_p1_d ), + .advance( next_ch ) + ); + +// RR Arbiter for priority 2 +wb_dma_ch_arb u3( + .clk( clk ), + .rst( rst ), + .req( req_p2 ), + .gnt( gnt_p2_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 3 +wb_dma_ch_arb u4( + .clk( clk ), + .rst( rst ), + .req( req_p3 ), + .gnt( gnt_p3_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 4 +wb_dma_ch_arb u5( + .clk( clk ), + .rst( rst ), + .req( req_p4 ), + .gnt( gnt_p4_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 5 +wb_dma_ch_arb u6( + .clk( clk ), + .rst( rst ), + .req( req_p5 ), + .gnt( gnt_p5_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 6 +wb_dma_ch_arb u7( + .clk( clk ), + .rst( rst ), + .req( req_p6 ), + .gnt( gnt_p6_d ), + .advance( next_ch ) + ); +// RR Arbiter for priority 7 +wb_dma_ch_arb u8( + .clk( clk ), + .rst( rst ), + .req( req_p7 ), + .gnt( gnt_p7_d ), + .advance( next_ch ) + ); + +// Select grant based on number of priorities +assign gnt_p0 = gnt_p0_d; +assign gnt_p1 = gnt_p1_d; +assign gnt_p2 = (pri_sel==2'd0) ? 5'h0 : gnt_p2_d; +assign gnt_p3 = (pri_sel==2'd0) ? 5'h0 : gnt_p3_d; +assign gnt_p4 = (pri_sel==2'd2) ? gnt_p4_d : 5'h0; +assign gnt_p5 = (pri_sel==2'd2) ? gnt_p5_d : 5'h0; +assign gnt_p6 = (pri_sel==2'd2) ? gnt_p6_d : 5'h0; +assign gnt_p7 = (pri_sel==2'd2) ? gnt_p7_d : 5'h0; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v new file mode 100644 index 000000000..264972353 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v @@ -0,0 +1,632 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA DMA Engine Core //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_de.v,v 1.3 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_de.v,v $ +// Revision 1.3 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.3 2001/06/13 02:26:48 rudi +// +// +// Small changes after running lint. +// +// Revision 1.2 2001/06/05 10:22:36 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:44 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_de(clk, rst, + + // WISHBONE MASTER INTERFACE 0 + mast0_go, mast0_we, mast0_adr, mast0_din, + mast0_dout, mast0_err, mast0_drdy, mast0_wait, + + // WISHBONE MASTER INTERFACE 1 + mast1_go, mast1_we, mast1_adr, mast1_din, + mast1_dout, mast1_err, mast1_drdy, mast1_wait, + + // DMA Engine Init & Setup + de_start, nd, csr, pointer, pointer_s, txsz, + adr0, adr1, am0, am1, + + // DMA Engine Register File Update Outputs + de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, ptr_set, + de_csr, de_txsz, de_adr0, de_adr1, de_fetch_descr, + + // DMA Engine Control Outputs + next_ch, de_ack, + + // DMA Engine Status + pause_req, paused, + dma_abort, dma_busy, dma_err, dma_done, dma_done_all + ); + +input clk, rst; + +// -------------------------------------- +// WISHBONE MASTER INTERFACE 0 + +output mast0_go; // Perform a Master Cycle +output mast0_we; // Read/Write +output [31:0] mast0_adr; // Address for the transfer +input [31:0] mast0_din; // Internal Input Data +output [31:0] mast0_dout; // Internal Output Data +input mast0_err; // Indicates an error has occurred +input mast0_drdy; // Indicated that either data is available + // during a read, or that the master can accept + // the next data during a write +output mast0_wait; // Tells the master to insert wait cycles + // because data can not be accepted/provided + +// -------------------------------------- +// WISHBONE MASTER INTERFACE 1 + +output mast1_go; // Perform a Master Cycle +output mast1_we; // Read/Write +output [31:0] mast1_adr; // Address for the transfer +input [31:0] mast1_din; // Internal Input Data +output [31:0] mast1_dout; // Internal Output Data +input mast1_err; // Indicates an error has occurred +input mast1_drdy; // Indicated that either data is available + // during a read, or that the master can accept + // the next data during a write +output mast1_wait; // Tells the master to insert wait cycles + // because data can not be accepted/provided + +// -------------------------------------- +// DMA Engine Signals + +// DMA Engine Init & Setup +input de_start; // Start DMA Engine Indicator +input nd; // Next Descriptor Indicator +input [31:0] csr; // Selected Channel CSR +input [31:0] pointer; // Linked List Descriptor pointer +input [31:0] pointer_s; // Previous Pointer +input [31:0] txsz; // Selected Channel Transfer Size +input [31:0] adr0, adr1; // Selected Channel Addresses +input [31:0] am0, am1; // Selected Channel Address Masks + +// DMA Engine Register File Update Outputs +output de_csr_we; // Write enable for csr register +output de_txsz_we; // Write enable for txsz register +output de_adr0_we; // Write enable for adr0 register +output de_adr1_we; // Write enable for adr1 register +output ptr_set; // Set Pointer as Valid +output [31:0] de_csr; // Write Data for CSR when loading External Desc. +output [11:0] de_txsz; // Write back data for txsz register +output [31:0] de_adr0; // Write back data for adr0 register +output [31:0] de_adr1; // Write back data for adr1 register +output de_fetch_descr; // Indicates that we are fetching a descriptor + +// DMA Engine Control Outputs +output next_ch; // Indicates the DMA Engine is done +output de_ack; + +// DMA Abort from RF (software forced abort) +input dma_abort; + +// DMA Engine Status +input pause_req; +output paused; +output dma_busy, dma_err, dma_done, dma_done_all; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +parameter [10:0] // synopsys enum state + IDLE = 11'b000_0000_0001, + READ = 11'b000_0000_0010, + WRITE = 11'b000_0000_0100, + UPDATE = 11'b000_0000_1000, + LD_DESC1 = 11'b000_0001_0000, + LD_DESC2 = 11'b000_0010_0000, + LD_DESC3 = 11'b000_0100_0000, + LD_DESC4 = 11'b000_1000_0000, + LD_DESC5 = 11'b001_0000_0000, + WB = 11'b010_0000_0000, + PAUSE = 11'b100_0000_0000; + +reg [10:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg [31:0] mast0_adr, mast1_adr; + +reg [29:0] adr0_cnt, adr1_cnt; +wire [29:0] adr0_cnt_next, adr1_cnt_next; +wire [29:0] adr0_cnt_next1, adr1_cnt_next1; +reg adr0_inc, adr1_inc; + +reg [8:0] chunk_cnt; +reg chunk_dec; + +reg [11:0] tsz_cnt; +reg tsz_dec; + +reg de_txsz_we; +reg de_csr_we; +reg de_adr0_we; +reg de_adr1_we; +reg ld_desc_sel; + +wire chunk_cnt_is_0_d; +reg chunk_cnt_is_0_r; +wire tsz_cnt_is_0_d; +reg tsz_cnt_is_0_r; + +reg read, write; +reg read_r, write_r; +wire rd_ack, wr_ack; +reg rd_ack_r; + +reg chunk_0; +wire done; +reg dma_done_d; +reg dma_done_r; +reg dma_abort_r; +reg next_ch; +wire read_hold, write_hold; +reg write_hold_r; + +reg [1:0] ptr_adr_low; +reg m0_go; +reg m0_we; +reg ptr_set; + +// Aliases +wire a0_inc_en = csr[4]; // Source Address (Adr 0) increment enable +wire a1_inc_en = csr[3]; // Dest. Address (Adr 1) increment enable +wire ptr_valid = pointer[0]; +wire use_ed = csr[`WDMA_USE_ED]; + +reg mast0_drdy_r; +reg paused; + +reg de_fetch_descr; // Indicates that we are fetching a descriptor +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + dma_done_r <= #1 dma_done; + +// Address Counter 0 (Source Address) +always @(posedge clk) + if(de_start | ptr_set) adr0_cnt <= #1 adr0[31:2]; + else + if(adr0_inc & a0_inc_en) adr0_cnt <= #1 adr0_cnt_next; + +// 30 Bit Incrementor (registered) +wb_dma_inc30r u0( .clk( clk ), + .in( adr0_cnt ), + .out( adr0_cnt_next1 ) ); + +assign adr0_cnt_next[1:0] = adr0_cnt_next1[1:0]; +assign adr0_cnt_next[2] = am0[4] ? adr0_cnt_next1[2] : adr0_cnt[2]; +assign adr0_cnt_next[3] = am0[5] ? adr0_cnt_next1[3] : adr0_cnt[3]; +assign adr0_cnt_next[4] = am0[6] ? adr0_cnt_next1[4] : adr0_cnt[4]; +assign adr0_cnt_next[5] = am0[7] ? adr0_cnt_next1[5] : adr0_cnt[5]; +assign adr0_cnt_next[6] = am0[8] ? adr0_cnt_next1[6] : adr0_cnt[6]; +assign adr0_cnt_next[7] = am0[9] ? adr0_cnt_next1[7] : adr0_cnt[7]; +assign adr0_cnt_next[8] = am0[10] ? adr0_cnt_next1[8] : adr0_cnt[8]; +assign adr0_cnt_next[9] = am0[11] ? adr0_cnt_next1[9] : adr0_cnt[9]; +assign adr0_cnt_next[10] = am0[12] ? adr0_cnt_next1[10] : adr0_cnt[10]; +assign adr0_cnt_next[11] = am0[13] ? adr0_cnt_next1[11] : adr0_cnt[11]; +assign adr0_cnt_next[12] = am0[14] ? adr0_cnt_next1[12] : adr0_cnt[12]; +assign adr0_cnt_next[13] = am0[15] ? adr0_cnt_next1[13] : adr0_cnt[13]; +assign adr0_cnt_next[14] = am0[16] ? adr0_cnt_next1[14] : adr0_cnt[14]; +assign adr0_cnt_next[15] = am0[17] ? adr0_cnt_next1[15] : adr0_cnt[15]; +assign adr0_cnt_next[16] = am0[18] ? adr0_cnt_next1[16] : adr0_cnt[16]; +assign adr0_cnt_next[17] = am0[19] ? adr0_cnt_next1[17] : adr0_cnt[17]; +assign adr0_cnt_next[18] = am0[20] ? adr0_cnt_next1[18] : adr0_cnt[18]; +assign adr0_cnt_next[19] = am0[21] ? adr0_cnt_next1[19] : adr0_cnt[19]; +assign adr0_cnt_next[20] = am0[22] ? adr0_cnt_next1[20] : adr0_cnt[20]; +assign adr0_cnt_next[21] = am0[23] ? adr0_cnt_next1[21] : adr0_cnt[21]; +assign adr0_cnt_next[22] = am0[24] ? adr0_cnt_next1[22] : adr0_cnt[22]; +assign adr0_cnt_next[23] = am0[25] ? adr0_cnt_next1[23] : adr0_cnt[23]; +assign adr0_cnt_next[24] = am0[26] ? adr0_cnt_next1[24] : adr0_cnt[24]; +assign adr0_cnt_next[25] = am0[27] ? adr0_cnt_next1[25] : adr0_cnt[25]; +assign adr0_cnt_next[26] = am0[28] ? adr0_cnt_next1[26] : adr0_cnt[26]; +assign adr0_cnt_next[27] = am0[29] ? adr0_cnt_next1[27] : adr0_cnt[27]; +assign adr0_cnt_next[28] = am0[30] ? adr0_cnt_next1[28] : adr0_cnt[28]; +assign adr0_cnt_next[29] = am0[31] ? adr0_cnt_next1[29] : adr0_cnt[29]; + + +// Address Counter 1 (Destination Address) +always @(posedge clk) + if(de_start | ptr_set) adr1_cnt <= #1 adr1[31:2]; + else + if(adr1_inc & a1_inc_en) adr1_cnt <= #1 adr1_cnt_next; + +// 30 Bit Incrementor (registered) +wb_dma_inc30r u1( .clk( clk ), + .in( adr1_cnt ), + .out( adr1_cnt_next1 ) ); + +assign adr1_cnt_next[1:0] = adr1_cnt_next1[1:0]; +assign adr1_cnt_next[2] = am1[4] ? adr1_cnt_next1[2] : adr1_cnt[2]; +assign adr1_cnt_next[3] = am1[5] ? adr1_cnt_next1[3] : adr1_cnt[3]; +assign adr1_cnt_next[4] = am1[6] ? adr1_cnt_next1[4] : adr1_cnt[4]; +assign adr1_cnt_next[5] = am1[7] ? adr1_cnt_next1[5] : adr1_cnt[5]; +assign adr1_cnt_next[6] = am1[8] ? adr1_cnt_next1[6] : adr1_cnt[6]; +assign adr1_cnt_next[7] = am1[9] ? adr1_cnt_next1[7] : adr1_cnt[7]; +assign adr1_cnt_next[8] = am1[10] ? adr1_cnt_next1[8] : adr1_cnt[8]; +assign adr1_cnt_next[9] = am1[11] ? adr1_cnt_next1[9] : adr1_cnt[9]; +assign adr1_cnt_next[10] = am1[12] ? adr1_cnt_next1[10] : adr1_cnt[10]; +assign adr1_cnt_next[11] = am1[13] ? adr1_cnt_next1[11] : adr1_cnt[11]; +assign adr1_cnt_next[12] = am1[14] ? adr1_cnt_next1[12] : adr1_cnt[12]; +assign adr1_cnt_next[13] = am1[15] ? adr1_cnt_next1[13] : adr1_cnt[13]; +assign adr1_cnt_next[14] = am1[16] ? adr1_cnt_next1[14] : adr1_cnt[14]; +assign adr1_cnt_next[15] = am1[17] ? adr1_cnt_next1[15] : adr1_cnt[15]; +assign adr1_cnt_next[16] = am1[18] ? adr1_cnt_next1[16] : adr1_cnt[16]; +assign adr1_cnt_next[17] = am1[19] ? adr1_cnt_next1[17] : adr1_cnt[17]; +assign adr1_cnt_next[18] = am1[20] ? adr1_cnt_next1[18] : adr1_cnt[18]; +assign adr1_cnt_next[19] = am1[21] ? adr1_cnt_next1[19] : adr1_cnt[19]; +assign adr1_cnt_next[20] = am1[22] ? adr1_cnt_next1[20] : adr1_cnt[20]; +assign adr1_cnt_next[21] = am1[23] ? adr1_cnt_next1[21] : adr1_cnt[21]; +assign adr1_cnt_next[22] = am1[24] ? adr1_cnt_next1[22] : adr1_cnt[22]; +assign adr1_cnt_next[23] = am1[25] ? adr1_cnt_next1[23] : adr1_cnt[23]; +assign adr1_cnt_next[24] = am1[26] ? adr1_cnt_next1[24] : adr1_cnt[24]; +assign adr1_cnt_next[25] = am1[27] ? adr1_cnt_next1[25] : adr1_cnt[25]; +assign adr1_cnt_next[26] = am1[28] ? adr1_cnt_next1[26] : adr1_cnt[26]; +assign adr1_cnt_next[27] = am1[29] ? adr1_cnt_next1[27] : adr1_cnt[27]; +assign adr1_cnt_next[28] = am1[30] ? adr1_cnt_next1[28] : adr1_cnt[28]; +assign adr1_cnt_next[29] = am1[31] ? adr1_cnt_next1[29] : adr1_cnt[29]; + +// Chunk Counter +always @(posedge clk) + if(de_start) chunk_cnt <= #1 txsz[24:16]; + else + if(chunk_dec & !chunk_cnt_is_0_r) chunk_cnt <= #1 chunk_cnt - 9'h1; + +assign chunk_cnt_is_0_d = (chunk_cnt == 9'h0); + +always @(posedge clk) + chunk_cnt_is_0_r <= #1 chunk_cnt_is_0_d; + +// Total Size Counter +always @(posedge clk) + if(de_start | ptr_set) tsz_cnt <= #1 txsz[11:0]; + else + if(tsz_dec & !tsz_cnt_is_0_r) tsz_cnt <= #1 tsz_cnt - 12'h1; + +assign tsz_cnt_is_0_d = (tsz_cnt == 12'h0) & !txsz[15]; + +always @(posedge clk) + tsz_cnt_is_0_r <= #1 tsz_cnt_is_0_d; + +// Counter Control Logic +always @(posedge clk) + chunk_dec <= #1 read & !read_r; + +always @(posedge clk) + tsz_dec <= #1 read & !read_r; + +//always @(posedge clk) +always @(rd_ack or read_r) + adr0_inc = rd_ack & read_r; + +//always @(posedge clk) +always @(wr_ack or write_r) + adr1_inc = wr_ack & write_r; + +// Done logic +always @(posedge clk) + chunk_0 <= #1 (txsz[24:16] == 9'h0); + +assign done = chunk_0 ? tsz_cnt_is_0_d : (tsz_cnt_is_0_d | chunk_cnt_is_0_d); +assign dma_done = dma_done_d & done; +assign dma_done_all = dma_done_d & (tsz_cnt_is_0_r | (nd & chunk_cnt_is_0_d)); + +always @(posedge clk) + next_ch <= #1 dma_done; + +// Register Update Outputs +assign de_txsz = ld_desc_sel ? mast0_din[11:0] : tsz_cnt; +assign de_adr0 = ld_desc_sel ? mast0_din : {adr0_cnt, 2'b00}; +assign de_adr1 = ld_desc_sel ? mast0_din : {adr1_cnt, 2'b00}; +assign de_csr = mast0_din; + +// Abort logic +always @(posedge clk) + dma_abort_r <= #1 dma_abort | mast0_err | mast1_err; + +assign dma_err = dma_abort_r; + +assign dma_busy = (state != IDLE); + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Interface Logic +// + +always @(posedge clk) + read_r <= #1 read; + +always @(posedge clk) + write_r <= #1 write; + +always @(posedge clk) + rd_ack_r <= #1 read_r; + +// Data Path +assign mast0_dout = m0_we ? {20'h0, tsz_cnt} : csr[2] ? mast1_din : mast0_din; +assign mast1_dout = csr[2] ? mast1_din : mast0_din; + +// Address Path +always @(posedge clk) + mast0_adr <= #1 m0_go ? + (m0_we ? pointer_s : {pointer[31:4], ptr_adr_low, 2'b00}) : + read ? {adr0_cnt, 2'b00} : {adr1_cnt, 2'b00}; + +always @(posedge clk) + mast1_adr <= #1 read ? {adr0_cnt, 2'b00} : {adr1_cnt, 2'b00}; + +// CTRL +assign write_hold = (read | write) & write_hold_r; + +always @(posedge clk) + write_hold_r <= #1 read | write; + +assign read_hold = done ? read : (read | write); + +assign mast0_go = (!csr[2] & read_hold) | (!csr[1] & write_hold) | m0_go; +assign mast1_go = ( csr[2] & read_hold) | ( csr[1] & write_hold); + +assign mast0_we = m0_go ? m0_we : (!csr[1] & write); +assign mast1_we = csr[1] & write; + +assign rd_ack = (csr[2] ? mast1_drdy : mast0_drdy); +assign wr_ack = (csr[1] ? mast1_drdy : mast0_drdy); + +assign mast0_wait = !((!csr[2] & read) | (!csr[1] & write)) & !m0_go; +assign mast1_wait = !(( csr[2] & read) | ( csr[1] & write)); + +always @(posedge clk) + mast0_drdy_r <= #1 mast0_drdy; + +assign de_ack = dma_done; + +//////////////////////////////////////////////////////////////////// +// +// State Machine +// + +always @(posedge clk or negedge rst) + if(!rst) state <= #1 IDLE; + else state <= #1 next_state; + +always @(state or pause_req or dma_abort_r or de_start or rd_ack or wr_ack or + done or ptr_valid or use_ed or mast0_drdy or mast0_drdy_r or csr or nd) + begin + next_state = state; // Default keep state + read = 1'b0; + write = 1'b0; + dma_done_d = 1'b0; + de_csr_we = 1'b0; + de_txsz_we = 1'b0; + de_adr0_we = 1'b0; + de_adr1_we = 1'b0; + de_fetch_descr = 1'b0; + + m0_go = 1'b0; + m0_we = 1'b0; + ptr_adr_low = 2'h0; + ptr_set = 1'b0; + ld_desc_sel = 1'b0; + paused = 1'b0; + + case(state) // synopsys parallel_case full_case + + IDLE: + begin + if(pause_req) next_state = PAUSE; + else + if(de_start & !csr[`WDMA_ERR]) + begin + if(use_ed & !ptr_valid) next_state = LD_DESC1; + else next_state = READ; + end + end + + PAUSE: + begin + paused = 1'b1; + if(!pause_req) next_state = IDLE; + end + + READ: // Read From Source + begin + if(dma_abort_r) next_state = UPDATE; + else + if(!rd_ack) read = 1'b1; + else + begin + write = 1'b1; + next_state = WRITE; + end + end + + WRITE: // Write To Destination + begin + if(dma_abort_r) next_state = UPDATE; + else + if(!wr_ack) write = 1'b1; + else + begin + if(done) next_state = UPDATE; + else + begin + read = 1'b1; + next_state = READ; + end + end + end + + UPDATE: // Update Registers + begin + dma_done_d = 1'b1; + de_txsz_we = 1'b1; + de_adr0_we = 1'b1; + de_adr1_we = 1'b1; + if(use_ed & csr[`WDMA_WRB] & nd) + begin + m0_we = 1'b1; + m0_go = 1'b1; + next_state = WB; + end + else next_state = IDLE; + end + + WB: + begin + m0_we = 1'b1; + if(mast0_drdy) + begin + next_state = IDLE; + end + else m0_go = 1'b1; + end + + LD_DESC1: // Load Descriptor from memory to registers + begin + ptr_adr_low = 2'h0; + ld_desc_sel = 1'b1; + m0_go = 1'b1; + de_csr_we = 1'b1; + de_txsz_we = 1'b1; + de_fetch_descr = 1'b1; + if(mast0_drdy) + begin + ptr_adr_low = 2'h1; + next_state = LD_DESC2; + end + end + + LD_DESC2: + begin + de_fetch_descr = 1'b1; + if(mast0_drdy_r) de_csr_we = 1'b1; + if(mast0_drdy_r) de_txsz_we = 1'b1; + ptr_adr_low = 2'h1; + ld_desc_sel = 1'b1; + m0_go = 1'b1; + if(mast0_drdy) + begin + ptr_adr_low = 2'h2; + next_state = LD_DESC3; + end + end + + LD_DESC3: + begin + de_fetch_descr = 1'b1; + if(mast0_drdy_r) de_adr0_we = 1'b1; + ptr_adr_low = 2'h2; + ld_desc_sel = 1'b1; + m0_go = 1'b1; + if(mast0_drdy) + begin + ptr_adr_low = 2'h3; + next_state = LD_DESC4; + end + end + + LD_DESC4: + begin + de_fetch_descr = 1'b1; + if(mast0_drdy_r) de_adr1_we = 1'b1; + ptr_adr_low = 2'h3; + ld_desc_sel = 1'b1; + if(mast0_drdy) + begin + next_state = LD_DESC5; + end + else m0_go = 1'b1; + end + + LD_DESC5: + begin + de_fetch_descr = 1'b1; + ptr_set = 1'b1; + next_state = READ; + end + + endcase + + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v new file mode 100644 index 000000000..68331c6e2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v @@ -0,0 +1,120 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Definitions //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_defines.v,v 1.5 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_defines.v,v $ +// Revision 1.5 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.4 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.3 2001/09/07 15:34:38 rudi +// +// Changed reset to active high. +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:11:09 rudi +// Initial Release +// +// +// + +`timescale 1ns / 10ps + +// This define selects how the slave interface determines if +// the internal register file or pass through mode are selected. +// This should be a simple address decoder. "wb_addr_i" is the +// WISHBONE address bus (32 bits wide). +// NOTE: The entire pass-through mode is implemented in combinatorial +// logic only. So the more address lines we look at and compare here +// the higher will be the initial delay when pass-through mode is selected. +// Here we look at the top 8 address bit. If they are all 1, the +// register file is selected. Use this with caution !!! +`define WDMA_REG_SEL (wb_addr_i[31:28] == rf_addr) + + +// DO NOT MODIFY BEYOND THIS POINT +// CSR Bits +`define WDMA_CH_EN 0 +`define WDMA_DST_SEL 1 +`define WDMA_SRC_SEL 2 +`define WDMA_INC_DST 3 +`define WDMA_INC_SRC 4 +`define WDMA_MODE 5 +`define WDMA_ARS 6 +`define WDMA_USE_ED 7 +`define WDMA_WRB 8 +`define WDMA_STOP 9 +`define WDMA_BUSY 10 +`define WDMA_DONE 11 +`define WDMA_ERR 12 +`define WDMA_ED_EOL 20 + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v new file mode 100644 index 000000000..73c4cb4b7 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v @@ -0,0 +1,96 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Primitives //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_inc30r.v,v 1.2 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_inc30r.v,v $ +// Revision 1.2 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:11:12 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_inc30r(clk, in, out); +input clk; +input [29:0] in; +output [29:0] out; + +// INC30_CENTER indicates the center bit of the 30 bit incrementor +// so it can be easily manually optimized for best performance +parameter INC30_CENTER = 16; + +reg [INC30_CENTER:0] out_r; + +always @(posedge clk) + out_r <= #1 in[(INC30_CENTER - 1):0] + 1; + +assign out[29:INC30_CENTER] = in[29:INC30_CENTER] + out_r[INC30_CENTER]; +assign out[(INC30_CENTER - 1):0] = out_r; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v new file mode 100644 index 000000000..4e42ec2b5 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v @@ -0,0 +1,146 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Priority Encoder Sub-Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_pri_enc_sub.v,v 1.4 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_pri_enc_sub.v,v $ +// Revision 1.4 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.3 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/08/07 08:00:43 rudi +// +// +// Split up priority encoder modules to separate files +// +// +// +// +// +// + +`include "wb_dma_defines.v" + +// Priority Encoder +// +// Determines the channel with the highest priority, also takes +// the valid bit in consideration + +module wb_dma_pri_enc_sub(valid, pri_in, pri_out); + +parameter [3:0] ch_conf = 4'b0000; +parameter [1:0] pri_sel = 2'd0; + +input valid; +input [2:0] pri_in; +output [7:0] pri_out; + +wire [7:0] pri_out; +reg [7:0] pri_out_d; +reg [7:0] pri_out_d0; +reg [7:0] pri_out_d1; +reg [7:0] pri_out_d2; + +assign pri_out = ch_conf[0] ? pri_out_d : 8'h0; + +// Select Configured Priority +always @(pri_sel or pri_out_d0 or pri_out_d1 or pri_out_d2) + case(pri_sel) // synopsys parallel_case full_case + 2'd0: pri_out_d = pri_out_d0; + 2'd1: pri_out_d = pri_out_d1; + 2'd2: pri_out_d = pri_out_d2; + endcase + +// 8 Priority Levels +always @(valid or pri_in) + if(!valid) pri_out_d2 = 8'b0000_0001; + else + if(pri_in==3'h0) pri_out_d2 = 8'b0000_0001; + else + if(pri_in==3'h1) pri_out_d2 = 8'b0000_0010; + else + if(pri_in==3'h2) pri_out_d2 = 8'b0000_0100; + else + if(pri_in==3'h3) pri_out_d2 = 8'b0000_1000; + else + if(pri_in==3'h4) pri_out_d2 = 8'b0001_0000; + else + if(pri_in==3'h5) pri_out_d2 = 8'b0010_0000; + else + if(pri_in==3'h6) pri_out_d2 = 8'b0100_0000; + else pri_out_d2 = 8'b1000_0000; + +// 4 Priority Levels +always @(valid or pri_in) + if(!valid) pri_out_d1 = 8'b0000_0001; + else + if(pri_in==3'h0) pri_out_d1 = 8'b0000_0001; + else + if(pri_in==3'h1) pri_out_d1 = 8'b0000_0010; + else + if(pri_in==3'h2) pri_out_d1 = 8'b0000_0100; + else pri_out_d1 = 8'b0000_1000; + +// 2 Priority Levels +always @(valid or pri_in) + if(!valid) pri_out_d0 = 8'b0000_0001; + else + if(pri_in==3'h0) pri_out_d0 = 8'b0000_0001; + else pri_out_d0 = 8'b0000_0010; + +endmodule + diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v new file mode 100644 index 000000000..cbc714c0a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v @@ -0,0 +1,1860 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Register File //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_rf.v,v 1.4 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_rf.v,v $ +// Revision 1.4 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.3 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.4 2001/06/14 08:50:46 rudi +// +// Changed name of channel register file module. +// +// Revision 1.3 2001/06/13 02:26:48 rudi +// +// +// Small changes after running lint. +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:11 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_rf(clk, rst, + + // WISHBONE Access + wb_rf_adr, wb_rf_din, wb_rf_dout, wb_rf_re, wb_rf_we, + + // WISHBONE Interrupt outputs + inta_o, intb_o, + + // DMA Registers Outputs + pointer0, pointer0_s, ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1, + pointer1, pointer1_s, ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1, + pointer2, pointer2_s, ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1, + pointer3, pointer3_s, ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1, + pointer4, pointer4_s, ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1, + pointer5, pointer5_s, ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1, + pointer6, pointer6_s, ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1, + pointer7, pointer7_s, ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1, + pointer8, pointer8_s, ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1, + pointer9, pointer9_s, ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1, + pointer10, pointer10_s, ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1, + pointer11, pointer11_s, ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1, + pointer12, pointer12_s, ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1, + pointer13, pointer13_s, ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1, + pointer14, pointer14_s, ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1, + pointer15, pointer15_s, ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1, + pointer16, pointer16_s, ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1, + pointer17, pointer17_s, ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1, + pointer18, pointer18_s, ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1, + pointer19, pointer19_s, ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1, + pointer20, pointer20_s, ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1, + pointer21, pointer21_s, ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1, + pointer22, pointer22_s, ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1, + pointer23, pointer23_s, ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1, + pointer24, pointer24_s, ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1, + pointer25, pointer25_s, ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1, + pointer26, pointer26_s, ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1, + pointer27, pointer27_s, ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1, + pointer28, pointer28_s, ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1, + pointer29, pointer29_s, ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1, + pointer30, pointer30_s, ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1, + + // DMA Registers Write Back Channel Select + ch_sel, ndnr, + + // DMA Engine Status + pause_req, paused, dma_abort, dma_busy, dma_err, dma_done, dma_done_all, + + // DMA Engine Reg File Update ctrl signals + de_csr, de_txsz, de_adr0, de_adr1, + de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, de_fetch_descr, dma_rest, + ptr_set + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +// chXX_conf = { CBUF, ED, ARS, EN } +parameter [3:0] ch0_conf = 4'h1; +parameter [3:0] ch1_conf = 4'h0; +parameter [3:0] ch2_conf = 4'h0; +parameter [3:0] ch3_conf = 4'h0; +parameter [3:0] ch4_conf = 4'h0; +parameter [3:0] ch5_conf = 4'h0; +parameter [3:0] ch6_conf = 4'h0; +parameter [3:0] ch7_conf = 4'h0; +parameter [3:0] ch8_conf = 4'h0; +parameter [3:0] ch9_conf = 4'h0; +parameter [3:0] ch10_conf = 4'h0; +parameter [3:0] ch11_conf = 4'h0; +parameter [3:0] ch12_conf = 4'h0; +parameter [3:0] ch13_conf = 4'h0; +parameter [3:0] ch14_conf = 4'h0; +parameter [3:0] ch15_conf = 4'h0; +parameter [3:0] ch16_conf = 4'h0; +parameter [3:0] ch17_conf = 4'h0; +parameter [3:0] ch18_conf = 4'h0; +parameter [3:0] ch19_conf = 4'h0; +parameter [3:0] ch20_conf = 4'h0; +parameter [3:0] ch21_conf = 4'h0; +parameter [3:0] ch22_conf = 4'h0; +parameter [3:0] ch23_conf = 4'h0; +parameter [3:0] ch24_conf = 4'h0; +parameter [3:0] ch25_conf = 4'h0; +parameter [3:0] ch26_conf = 4'h0; +parameter [3:0] ch27_conf = 4'h0; +parameter [3:0] ch28_conf = 4'h0; +parameter [3:0] ch29_conf = 4'h0; +parameter [3:0] ch30_conf = 4'h0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk, rst; + +// WISHBONE Access +input [7:0] wb_rf_adr; +input [31:0] wb_rf_din; +output [31:0] wb_rf_dout; +input wb_rf_re; +input wb_rf_we; + +// WISHBONE Interrupt outputs +output inta_o, intb_o; + +// Channel Registers Inputs +output [31:0] pointer0, pointer0_s, ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1; +output [31:0] pointer1, pointer1_s, ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1; +output [31:0] pointer2, pointer2_s, ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1; +output [31:0] pointer3, pointer3_s, ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1; +output [31:0] pointer4, pointer4_s, ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1; +output [31:0] pointer5, pointer5_s, ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1; +output [31:0] pointer6, pointer6_s, ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1; +output [31:0] pointer7, pointer7_s, ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1; +output [31:0] pointer8, pointer8_s, ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1; +output [31:0] pointer9, pointer9_s, ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1; +output [31:0] pointer10, pointer10_s, ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1; +output [31:0] pointer11, pointer11_s, ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1; +output [31:0] pointer12, pointer12_s, ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1; +output [31:0] pointer13, pointer13_s, ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1; +output [31:0] pointer14, pointer14_s, ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1; +output [31:0] pointer15, pointer15_s, ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1; +output [31:0] pointer16, pointer16_s, ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1; +output [31:0] pointer17, pointer17_s, ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1; +output [31:0] pointer18, pointer18_s, ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1; +output [31:0] pointer19, pointer19_s, ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1; +output [31:0] pointer20, pointer20_s, ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1; +output [31:0] pointer21, pointer21_s, ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1; +output [31:0] pointer22, pointer22_s, ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1; +output [31:0] pointer23, pointer23_s, ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1; +output [31:0] pointer24, pointer24_s, ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1; +output [31:0] pointer25, pointer25_s, ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1; +output [31:0] pointer26, pointer26_s, ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1; +output [31:0] pointer27, pointer27_s, ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1; +output [31:0] pointer28, pointer28_s, ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1; +output [31:0] pointer29, pointer29_s, ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1; +output [31:0] pointer30, pointer30_s, ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1; + +input [4:0] ch_sel; // Write Back Channel Select +input [30:0] ndnr; // Next Descriptor No Request + +// DMA Engine Abort +output dma_abort; + +// DMA Engine Status +output pause_req; +input paused; +input dma_busy, dma_err, dma_done, dma_done_all; + +// DMA Engine Reg File Update ctrl signals +input [31:0] de_csr; +input [11:0] de_txsz; +input [31:0] de_adr0; +input [31:0] de_adr1; +input de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, ptr_set; +input de_fetch_descr; +input [30:0] dma_rest; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [31:0] wb_rf_dout; +reg inta_o, intb_o; +reg [30:0] int_maska_r, int_maskb_r; +wire [31:0] int_maska, int_maskb; +wire [31:0] int_srca, int_srcb; +wire int_maska_we, int_maskb_we; +wire [30:0] ch_int; +wire csr_we; +wire [31:0] csr; +reg [7:0] csr_r; + +wire [30:0] ch_stop; +wire [30:0] ch_dis; + +wire [31:0] ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1; +wire [31:0] ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1; +wire [31:0] ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1; +wire [31:0] ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1; +wire [31:0] ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1; +wire [31:0] ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1; +wire [31:0] ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1; +wire [31:0] ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1; +wire [31:0] ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1; +wire [31:0] ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1; +wire [31:0] ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1; +wire [31:0] ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1; +wire [31:0] ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1; +wire [31:0] ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1; +wire [31:0] ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1; +wire [31:0] ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1; +wire [31:0] ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1; +wire [31:0] ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1; +wire [31:0] ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1; +wire [31:0] ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1; +wire [31:0] ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1; +wire [31:0] ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1; +wire [31:0] ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1; +wire [31:0] ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1; +wire [31:0] ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1; +wire [31:0] ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1; +wire [31:0] ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1; +wire [31:0] ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1; +wire [31:0] ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1; +wire [31:0] ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1; +wire [31:0] ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1; + +wire [31:0] sw_pointer0, sw_pointer1, sw_pointer2, sw_pointer3; +wire [31:0] sw_pointer4, sw_pointer5, sw_pointer6, sw_pointer7; +wire [31:0] sw_pointer8, sw_pointer9, sw_pointer10, sw_pointer11; +wire [31:0] sw_pointer12, sw_pointer13, sw_pointer14, sw_pointer15; +wire [31:0] sw_pointer16, sw_pointer17, sw_pointer18, sw_pointer19; +wire [31:0] sw_pointer20, sw_pointer21, sw_pointer22, sw_pointer23; +wire [31:0] sw_pointer24, sw_pointer25, sw_pointer26, sw_pointer27; +wire [31:0] sw_pointer28, sw_pointer29, sw_pointer30; + +//////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign int_maska = {1'h0, int_maska_r}; +assign int_maskb = {1'h0, int_maskb_r}; +assign csr = {31'h0, paused}; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign dma_abort = |ch_stop; +assign pause_req = csr_r[0]; + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Register Read Logic +// + +always @(posedge clk) + case(wb_rf_adr) // synopsys parallel_case full_case + 8'h0: wb_rf_dout <= #1 csr; + 8'h1: wb_rf_dout <= #1 int_maska; + 8'h2: wb_rf_dout <= #1 int_maskb; + 8'h3: wb_rf_dout <= #1 int_srca; + 8'h4: wb_rf_dout <= #1 int_srcb; + + 8'h8: wb_rf_dout <= #1 ch0_csr; + 8'h9: wb_rf_dout <= #1 ch0_txsz; + 8'ha: wb_rf_dout <= #1 ch0_adr0; + 8'hb: wb_rf_dout <= #1 ch0_am0; + 8'hc: wb_rf_dout <= #1 ch0_adr1; + 8'hd: wb_rf_dout <= #1 ch0_am1; + 8'he: wb_rf_dout <= #1 pointer0; + 8'hf: wb_rf_dout <= #1 sw_pointer0; + + 8'h10: wb_rf_dout <= #1 ch1_conf[0] ? ch1_csr : 32'h0; + 8'h11: wb_rf_dout <= #1 ch1_conf[0] ? ch1_txsz : 32'h0; + 8'h12: wb_rf_dout <= #1 ch1_conf[0] ? ch1_adr0 : 32'h0; + 8'h13: wb_rf_dout <= #1 ch1_conf[0] ? ch1_am0 : 32'h0; + 8'h14: wb_rf_dout <= #1 ch1_conf[0] ? ch1_adr1 : 32'h0; + 8'h15: wb_rf_dout <= #1 ch1_conf[0] ? ch1_am1 : 32'h0; + 8'h16: wb_rf_dout <= #1 ch1_conf[0] ? pointer1 : 32'h0; + 8'h17: wb_rf_dout <= #1 ch1_conf[0] ? sw_pointer1 : 32'h0; + + 8'h18: wb_rf_dout <= #1 ch2_conf[0] ? ch2_csr : 32'h0; + 8'h19: wb_rf_dout <= #1 ch2_conf[0] ? ch2_txsz : 32'h0; + 8'h1a: wb_rf_dout <= #1 ch2_conf[0] ? ch2_adr0 : 32'h0; + 8'h1b: wb_rf_dout <= #1 ch2_conf[0] ? ch2_am0 : 32'h0; + 8'h1c: wb_rf_dout <= #1 ch2_conf[0] ? ch2_adr1 : 32'h0; + 8'h1d: wb_rf_dout <= #1 ch2_conf[0] ? ch2_am1 : 32'h0; + 8'h1e: wb_rf_dout <= #1 ch2_conf[0] ? pointer2 : 32'h0; + 8'h1f: wb_rf_dout <= #1 ch2_conf[0] ? sw_pointer2 : 32'h0; + + 8'h20: wb_rf_dout <= #1 ch3_conf[0] ? ch3_csr : 32'h0; + 8'h21: wb_rf_dout <= #1 ch3_conf[0] ? ch3_txsz : 32'h0; + 8'h22: wb_rf_dout <= #1 ch3_conf[0] ? ch3_adr0 : 32'h0; + 8'h23: wb_rf_dout <= #1 ch3_conf[0] ? ch3_am0 : 32'h0; + 8'h24: wb_rf_dout <= #1 ch3_conf[0] ? ch3_adr1 : 32'h0; + 8'h25: wb_rf_dout <= #1 ch3_conf[0] ? ch3_am1 : 32'h0; + 8'h26: wb_rf_dout <= #1 ch3_conf[0] ? pointer3 : 32'h0; + 8'h27: wb_rf_dout <= #1 ch3_conf[0] ? sw_pointer3 : 32'h0; + + 8'h28: wb_rf_dout <= #1 ch4_conf[0] ? ch4_csr : 32'h0; + 8'h29: wb_rf_dout <= #1 ch4_conf[0] ? ch4_txsz : 32'h0; + 8'h2a: wb_rf_dout <= #1 ch4_conf[0] ? ch4_adr0 : 32'h0; + 8'h2b: wb_rf_dout <= #1 ch4_conf[0] ? ch4_am0 : 32'h0; + 8'h2c: wb_rf_dout <= #1 ch4_conf[0] ? ch4_adr1 : 32'h0; + 8'h2d: wb_rf_dout <= #1 ch4_conf[0] ? ch4_am1 : 32'h0; + 8'h2e: wb_rf_dout <= #1 ch4_conf[0] ? pointer4 : 32'h0; + 8'h2f: wb_rf_dout <= #1 ch4_conf[0] ? sw_pointer4 : 32'h0; + + 8'h30: wb_rf_dout <= #1 ch5_conf[0] ? ch5_csr : 32'h0; + 8'h31: wb_rf_dout <= #1 ch5_conf[0] ? ch5_txsz : 32'h0; + 8'h32: wb_rf_dout <= #1 ch5_conf[0] ? ch5_adr0 : 32'h0; + 8'h33: wb_rf_dout <= #1 ch5_conf[0] ? ch5_am0 : 32'h0; + 8'h34: wb_rf_dout <= #1 ch5_conf[0] ? ch5_adr1 : 32'h0; + 8'h35: wb_rf_dout <= #1 ch5_conf[0] ? ch5_am1 : 32'h0; + 8'h36: wb_rf_dout <= #1 ch5_conf[0] ? pointer5 : 32'h0; + 8'h37: wb_rf_dout <= #1 ch5_conf[0] ? sw_pointer5 : 32'h0; + + 8'h38: wb_rf_dout <= #1 ch6_conf[0] ? ch6_csr : 32'h0; + 8'h39: wb_rf_dout <= #1 ch6_conf[0] ? ch6_txsz : 32'h0; + 8'h3a: wb_rf_dout <= #1 ch6_conf[0] ? ch6_adr0 : 32'h0; + 8'h3b: wb_rf_dout <= #1 ch6_conf[0] ? ch6_am0 : 32'h0; + 8'h3c: wb_rf_dout <= #1 ch6_conf[0] ? ch6_adr1 : 32'h0; + 8'h3d: wb_rf_dout <= #1 ch6_conf[0] ? ch6_am1 : 32'h0; + 8'h3e: wb_rf_dout <= #1 ch6_conf[0] ? pointer6 : 32'h0; + 8'h3f: wb_rf_dout <= #1 ch6_conf[0] ? sw_pointer6 : 32'h0; + + 8'h40: wb_rf_dout <= #1 ch7_conf[0] ? ch7_csr : 32'h0; + 8'h41: wb_rf_dout <= #1 ch7_conf[0] ? ch7_txsz : 32'h0; + 8'h42: wb_rf_dout <= #1 ch7_conf[0] ? ch7_adr0 : 32'h0; + 8'h43: wb_rf_dout <= #1 ch7_conf[0] ? ch7_am0 : 32'h0; + 8'h44: wb_rf_dout <= #1 ch7_conf[0] ? ch7_adr1 : 32'h0; + 8'h45: wb_rf_dout <= #1 ch7_conf[0] ? ch7_am1 : 32'h0; + 8'h46: wb_rf_dout <= #1 ch7_conf[0] ? pointer7 : 32'h0; + 8'h47: wb_rf_dout <= #1 ch7_conf[0] ? sw_pointer7 : 32'h0; + + 8'h48: wb_rf_dout <= #1 ch8_conf[0] ? ch8_csr : 32'h0; + 8'h49: wb_rf_dout <= #1 ch8_conf[0] ? ch8_txsz : 32'h0; + 8'h4a: wb_rf_dout <= #1 ch8_conf[0] ? ch8_adr0 : 32'h0; + 8'h4b: wb_rf_dout <= #1 ch8_conf[0] ? ch8_am0 : 32'h0; + 8'h4c: wb_rf_dout <= #1 ch8_conf[0] ? ch8_adr1 : 32'h0; + 8'h4d: wb_rf_dout <= #1 ch8_conf[0] ? ch8_am1 : 32'h0; + 8'h4e: wb_rf_dout <= #1 ch8_conf[0] ? pointer8 : 32'h0; + 8'h4f: wb_rf_dout <= #1 ch8_conf[0] ? sw_pointer8 : 32'h0; + + 8'h50: wb_rf_dout <= #1 ch9_conf[0] ? ch9_csr : 32'h0; + 8'h51: wb_rf_dout <= #1 ch9_conf[0] ? ch9_txsz : 32'h0; + 8'h52: wb_rf_dout <= #1 ch9_conf[0] ? ch9_adr0 : 32'h0; + 8'h53: wb_rf_dout <= #1 ch9_conf[0] ? ch9_am0 : 32'h0; + 8'h54: wb_rf_dout <= #1 ch9_conf[0] ? ch9_adr1 : 32'h0; + 8'h55: wb_rf_dout <= #1 ch9_conf[0] ? ch9_am1 : 32'h0; + 8'h56: wb_rf_dout <= #1 ch9_conf[0] ? pointer9 : 32'h0; + 8'h57: wb_rf_dout <= #1 ch9_conf[0] ? sw_pointer9 : 32'h0; + + 8'h58: wb_rf_dout <= #1 ch10_conf[0] ? ch10_csr : 32'h0; + 8'h59: wb_rf_dout <= #1 ch10_conf[0] ? ch10_txsz : 32'h0; + 8'h5a: wb_rf_dout <= #1 ch10_conf[0] ? ch10_adr0 : 32'h0; + 8'h5b: wb_rf_dout <= #1 ch10_conf[0] ? ch10_am0 : 32'h0; + 8'h5c: wb_rf_dout <= #1 ch10_conf[0] ? ch10_adr1 : 32'h0; + 8'h5d: wb_rf_dout <= #1 ch10_conf[0] ? ch10_am1 : 32'h0; + 8'h5e: wb_rf_dout <= #1 ch10_conf[0] ? pointer10 : 32'h0; + 8'h5f: wb_rf_dout <= #1 ch10_conf[0] ? sw_pointer10 : 32'h0; + + 8'h60: wb_rf_dout <= #1 ch11_conf[0] ? ch11_csr : 32'h0; + 8'h61: wb_rf_dout <= #1 ch11_conf[0] ? ch11_txsz : 32'h0; + 8'h62: wb_rf_dout <= #1 ch11_conf[0] ? ch11_adr0 : 32'h0; + 8'h63: wb_rf_dout <= #1 ch11_conf[0] ? ch11_am0 : 32'h0; + 8'h64: wb_rf_dout <= #1 ch11_conf[0] ? ch11_adr1 : 32'h0; + 8'h65: wb_rf_dout <= #1 ch11_conf[0] ? ch11_am1 : 32'h0; + 8'h66: wb_rf_dout <= #1 ch11_conf[0] ? pointer11 : 32'h0; + 8'h67: wb_rf_dout <= #1 ch11_conf[0] ? sw_pointer11 : 32'h0; + + 8'h68: wb_rf_dout <= #1 ch12_conf[0] ? ch12_csr : 32'h0; + 8'h69: wb_rf_dout <= #1 ch12_conf[0] ? ch12_txsz : 32'h0; + 8'h6a: wb_rf_dout <= #1 ch12_conf[0] ? ch12_adr0 : 32'h0; + 8'h6b: wb_rf_dout <= #1 ch12_conf[0] ? ch12_am0 : 32'h0; + 8'h6c: wb_rf_dout <= #1 ch12_conf[0] ? ch12_adr1 : 32'h0; + 8'h6d: wb_rf_dout <= #1 ch12_conf[0] ? ch12_am1 : 32'h0; + 8'h6e: wb_rf_dout <= #1 ch12_conf[0] ? pointer12 : 32'h0; + 8'h6f: wb_rf_dout <= #1 ch12_conf[0] ? sw_pointer12 : 32'h0; + + 8'h70: wb_rf_dout <= #1 ch13_conf[0] ? ch13_csr : 32'h0; + 8'h71: wb_rf_dout <= #1 ch13_conf[0] ? ch13_txsz : 32'h0; + 8'h72: wb_rf_dout <= #1 ch13_conf[0] ? ch13_adr0 : 32'h0; + 8'h73: wb_rf_dout <= #1 ch13_conf[0] ? ch13_am0 : 32'h0; + 8'h74: wb_rf_dout <= #1 ch13_conf[0] ? ch13_adr1 : 32'h0; + 8'h75: wb_rf_dout <= #1 ch13_conf[0] ? ch13_am1 : 32'h0; + 8'h76: wb_rf_dout <= #1 ch13_conf[0] ? pointer13 : 32'h0; + 8'h77: wb_rf_dout <= #1 ch13_conf[0] ? sw_pointer13 : 32'h0; + + 8'h78: wb_rf_dout <= #1 ch14_conf[0] ? ch14_csr : 32'h0; + 8'h79: wb_rf_dout <= #1 ch14_conf[0] ? ch14_txsz : 32'h0; + 8'h7a: wb_rf_dout <= #1 ch14_conf[0] ? ch14_adr0 : 32'h0; + 8'h7b: wb_rf_dout <= #1 ch14_conf[0] ? ch14_am0 : 32'h0; + 8'h7c: wb_rf_dout <= #1 ch14_conf[0] ? ch14_adr1 : 32'h0; + 8'h7d: wb_rf_dout <= #1 ch14_conf[0] ? ch14_am1 : 32'h0; + 8'h7e: wb_rf_dout <= #1 ch14_conf[0] ? pointer14 : 32'h0; + 8'h7f: wb_rf_dout <= #1 ch14_conf[0] ? sw_pointer14 : 32'h0; + + 8'h80: wb_rf_dout <= #1 ch15_conf[0] ? ch15_csr : 32'h0; + 8'h81: wb_rf_dout <= #1 ch15_conf[0] ? ch15_txsz : 32'h0; + 8'h82: wb_rf_dout <= #1 ch15_conf[0] ? ch15_adr0 : 32'h0; + 8'h83: wb_rf_dout <= #1 ch15_conf[0] ? ch15_am0 : 32'h0; + 8'h84: wb_rf_dout <= #1 ch15_conf[0] ? ch15_adr1 : 32'h0; + 8'h85: wb_rf_dout <= #1 ch15_conf[0] ? ch15_am1 : 32'h0; + 8'h86: wb_rf_dout <= #1 ch15_conf[0] ? pointer15 : 32'h0; + 8'h87: wb_rf_dout <= #1 ch15_conf[0] ? sw_pointer15 : 32'h0; + + 8'h88: wb_rf_dout <= #1 ch16_conf[0] ? ch16_csr : 32'h0; + 8'h89: wb_rf_dout <= #1 ch16_conf[0] ? ch16_txsz : 32'h0; + 8'h8a: wb_rf_dout <= #1 ch16_conf[0] ? ch16_adr0 : 32'h0; + 8'h8b: wb_rf_dout <= #1 ch16_conf[0] ? ch16_am0 : 32'h0; + 8'h8c: wb_rf_dout <= #1 ch16_conf[0] ? ch16_adr1 : 32'h0; + 8'h8d: wb_rf_dout <= #1 ch16_conf[0] ? ch16_am1 : 32'h0; + 8'h8e: wb_rf_dout <= #1 ch16_conf[0] ? pointer16 : 32'h0; + 8'h8f: wb_rf_dout <= #1 ch16_conf[0] ? sw_pointer16 : 32'h0; + + 8'h90: wb_rf_dout <= #1 ch17_conf[0] ? ch17_csr : 32'h0; + 8'h91: wb_rf_dout <= #1 ch17_conf[0] ? ch17_txsz : 32'h0; + 8'h92: wb_rf_dout <= #1 ch17_conf[0] ? ch17_adr0 : 32'h0; + 8'h93: wb_rf_dout <= #1 ch17_conf[0] ? ch17_am0 : 32'h0; + 8'h94: wb_rf_dout <= #1 ch17_conf[0] ? ch17_adr1 : 32'h0; + 8'h95: wb_rf_dout <= #1 ch17_conf[0] ? ch17_am1 : 32'h0; + 8'h96: wb_rf_dout <= #1 ch17_conf[0] ? pointer17 : 32'h0; + 8'h97: wb_rf_dout <= #1 ch17_conf[0] ? sw_pointer17 : 32'h0; + + 8'h98: wb_rf_dout <= #1 ch18_conf[0] ? ch18_csr : 32'h0; + 8'h99: wb_rf_dout <= #1 ch18_conf[0] ? ch18_txsz : 32'h0; + 8'h9a: wb_rf_dout <= #1 ch18_conf[0] ? ch18_adr0 : 32'h0; + 8'h9b: wb_rf_dout <= #1 ch18_conf[0] ? ch18_am0 : 32'h0; + 8'h9c: wb_rf_dout <= #1 ch18_conf[0] ? ch18_adr1 : 32'h0; + 8'h9d: wb_rf_dout <= #1 ch18_conf[0] ? ch18_am1 : 32'h0; + 8'h9e: wb_rf_dout <= #1 ch18_conf[0] ? pointer18 : 32'h0; + 8'h9f: wb_rf_dout <= #1 ch18_conf[0] ? sw_pointer18 : 32'h0; + + 8'ha0: wb_rf_dout <= #1 ch19_conf[0] ? ch19_csr : 32'h0; + 8'ha1: wb_rf_dout <= #1 ch19_conf[0] ? ch19_txsz : 32'h0; + 8'ha2: wb_rf_dout <= #1 ch19_conf[0] ? ch19_adr0 : 32'h0; + 8'ha3: wb_rf_dout <= #1 ch19_conf[0] ? ch19_am0 : 32'h0; + 8'ha4: wb_rf_dout <= #1 ch19_conf[0] ? ch19_adr1 : 32'h0; + 8'ha5: wb_rf_dout <= #1 ch19_conf[0] ? ch19_am1 : 32'h0; + 8'ha6: wb_rf_dout <= #1 ch19_conf[0] ? pointer19 : 32'h0; + 8'ha7: wb_rf_dout <= #1 ch19_conf[0] ? sw_pointer19 : 32'h0; + + 8'ha8: wb_rf_dout <= #1 ch20_conf[0] ? ch20_csr : 32'h0; + 8'ha9: wb_rf_dout <= #1 ch20_conf[0] ? ch20_txsz : 32'h0; + 8'haa: wb_rf_dout <= #1 ch20_conf[0] ? ch20_adr0 : 32'h0; + 8'hab: wb_rf_dout <= #1 ch20_conf[0] ? ch20_am0 : 32'h0; + 8'hac: wb_rf_dout <= #1 ch20_conf[0] ? ch20_adr1 : 32'h0; + 8'had: wb_rf_dout <= #1 ch20_conf[0] ? ch20_am1 : 32'h0; + 8'hae: wb_rf_dout <= #1 ch20_conf[0] ? pointer20 : 32'h0; + 8'haf: wb_rf_dout <= #1 ch20_conf[0] ? sw_pointer20 : 32'h0; + + 8'hb0: wb_rf_dout <= #1 ch21_conf[0] ? ch21_csr : 32'h0; + 8'hb1: wb_rf_dout <= #1 ch21_conf[0] ? ch21_txsz : 32'h0; + 8'hb2: wb_rf_dout <= #1 ch21_conf[0] ? ch21_adr0 : 32'h0; + 8'hb3: wb_rf_dout <= #1 ch21_conf[0] ? ch21_am0 : 32'h0; + 8'hb4: wb_rf_dout <= #1 ch21_conf[0] ? ch21_adr1 : 32'h0; + 8'hb5: wb_rf_dout <= #1 ch21_conf[0] ? ch21_am1 : 32'h0; + 8'hb6: wb_rf_dout <= #1 ch21_conf[0] ? pointer21 : 32'h0; + 8'hb7: wb_rf_dout <= #1 ch21_conf[0] ? sw_pointer21 : 32'h0; + + 8'hb8: wb_rf_dout <= #1 ch22_conf[0] ? ch22_csr : 32'h0; + 8'hb9: wb_rf_dout <= #1 ch22_conf[0] ? ch22_txsz : 32'h0; + 8'hba: wb_rf_dout <= #1 ch22_conf[0] ? ch22_adr0 : 32'h0; + 8'hbb: wb_rf_dout <= #1 ch22_conf[0] ? ch22_am0 : 32'h0; + 8'hbc: wb_rf_dout <= #1 ch22_conf[0] ? ch22_adr1 : 32'h0; + 8'hbd: wb_rf_dout <= #1 ch22_conf[0] ? ch22_am1 : 32'h0; + 8'hbe: wb_rf_dout <= #1 ch22_conf[0] ? pointer22 : 32'h0; + 8'hbf: wb_rf_dout <= #1 ch22_conf[0] ? sw_pointer22 : 32'h0; + + 8'hc0: wb_rf_dout <= #1 ch23_conf[0] ? ch23_csr : 32'h0; + 8'hc1: wb_rf_dout <= #1 ch23_conf[0] ? ch23_txsz : 32'h0; + 8'hc2: wb_rf_dout <= #1 ch23_conf[0] ? ch23_adr0 : 32'h0; + 8'hc3: wb_rf_dout <= #1 ch23_conf[0] ? ch23_am0 : 32'h0; + 8'hc4: wb_rf_dout <= #1 ch23_conf[0] ? ch23_adr1 : 32'h0; + 8'hc5: wb_rf_dout <= #1 ch23_conf[0] ? ch23_am1 : 32'h0; + 8'hc6: wb_rf_dout <= #1 ch23_conf[0] ? pointer23 : 32'h0; + 8'hc7: wb_rf_dout <= #1 ch23_conf[0] ? sw_pointer23 : 32'h0; + + 8'hc8: wb_rf_dout <= #1 ch24_conf[0] ? ch24_csr : 32'h0; + 8'hc9: wb_rf_dout <= #1 ch24_conf[0] ? ch24_txsz : 32'h0; + 8'hca: wb_rf_dout <= #1 ch24_conf[0] ? ch24_adr0 : 32'h0; + 8'hcb: wb_rf_dout <= #1 ch24_conf[0] ? ch24_am0 : 32'h0; + 8'hcc: wb_rf_dout <= #1 ch24_conf[0] ? ch24_adr1 : 32'h0; + 8'hcd: wb_rf_dout <= #1 ch24_conf[0] ? ch24_am1 : 32'h0; + 8'hce: wb_rf_dout <= #1 ch24_conf[0] ? pointer24 : 32'h0; + 8'hcf: wb_rf_dout <= #1 ch24_conf[0] ? sw_pointer24 : 32'h0; + + 8'hd0: wb_rf_dout <= #1 ch25_conf[0] ? ch25_csr : 32'h0; + 8'hd1: wb_rf_dout <= #1 ch25_conf[0] ? ch25_txsz : 32'h0; + 8'hd2: wb_rf_dout <= #1 ch25_conf[0] ? ch25_adr0 : 32'h0; + 8'hd3: wb_rf_dout <= #1 ch25_conf[0] ? ch25_am0 : 32'h0; + 8'hd4: wb_rf_dout <= #1 ch25_conf[0] ? ch25_adr1 : 32'h0; + 8'hd5: wb_rf_dout <= #1 ch25_conf[0] ? ch25_am1 : 32'h0; + 8'hd6: wb_rf_dout <= #1 ch25_conf[0] ? pointer25 : 32'h0; + 8'hd7: wb_rf_dout <= #1 ch25_conf[0] ? sw_pointer25 : 32'h0; + + 8'hd8: wb_rf_dout <= #1 ch26_conf[0] ? ch26_csr : 32'h0; + 8'hd9: wb_rf_dout <= #1 ch26_conf[0] ? ch26_txsz : 32'h0; + 8'hda: wb_rf_dout <= #1 ch26_conf[0] ? ch26_adr0 : 32'h0; + 8'hdb: wb_rf_dout <= #1 ch26_conf[0] ? ch26_am0 : 32'h0; + 8'hdc: wb_rf_dout <= #1 ch26_conf[0] ? ch26_adr1 : 32'h0; + 8'hdd: wb_rf_dout <= #1 ch26_conf[0] ? ch26_am1 : 32'h0; + 8'hde: wb_rf_dout <= #1 ch26_conf[0] ? pointer26 : 32'h0; + 8'hdf: wb_rf_dout <= #1 ch26_conf[0] ? sw_pointer26 : 32'h0; + + 8'he0: wb_rf_dout <= #1 ch27_conf[0] ? ch27_csr : 32'h0; + 8'he1: wb_rf_dout <= #1 ch27_conf[0] ? ch27_txsz : 32'h0; + 8'he2: wb_rf_dout <= #1 ch27_conf[0] ? ch27_adr0 : 32'h0; + 8'he3: wb_rf_dout <= #1 ch27_conf[0] ? ch27_am0 : 32'h0; + 8'he4: wb_rf_dout <= #1 ch27_conf[0] ? ch27_adr1 : 32'h0; + 8'he5: wb_rf_dout <= #1 ch27_conf[0] ? ch27_am1 : 32'h0; + 8'he6: wb_rf_dout <= #1 ch27_conf[0] ? pointer27 : 32'h0; + 8'he7: wb_rf_dout <= #1 ch27_conf[0] ? sw_pointer27 : 32'h0; + + 8'he8: wb_rf_dout <= #1 ch28_conf[0] ? ch28_csr : 32'h0; + 8'he9: wb_rf_dout <= #1 ch28_conf[0] ? ch28_txsz : 32'h0; + 8'hea: wb_rf_dout <= #1 ch28_conf[0] ? ch28_adr0 : 32'h0; + 8'heb: wb_rf_dout <= #1 ch28_conf[0] ? ch28_am0 : 32'h0; + 8'hec: wb_rf_dout <= #1 ch28_conf[0] ? ch28_adr1 : 32'h0; + 8'hed: wb_rf_dout <= #1 ch28_conf[0] ? ch28_am1 : 32'h0; + 8'hee: wb_rf_dout <= #1 ch28_conf[0] ? pointer28 : 32'h0; + 8'hef: wb_rf_dout <= #1 ch28_conf[0] ? sw_pointer28 : 32'h0; + + 8'hf0: wb_rf_dout <= #1 ch29_conf[0] ? ch29_csr : 32'h0; + 8'hf1: wb_rf_dout <= #1 ch29_conf[0] ? ch29_txsz : 32'h0; + 8'hf2: wb_rf_dout <= #1 ch29_conf[0] ? ch29_adr0 : 32'h0; + 8'hf3: wb_rf_dout <= #1 ch29_conf[0] ? ch29_am0 : 32'h0; + 8'hf4: wb_rf_dout <= #1 ch29_conf[0] ? ch29_adr1 : 32'h0; + 8'hf5: wb_rf_dout <= #1 ch29_conf[0] ? ch29_am1 : 32'h0; + 8'hf6: wb_rf_dout <= #1 ch29_conf[0] ? pointer29 : 32'h0; + 8'hf7: wb_rf_dout <= #1 ch29_conf[0] ? sw_pointer29 : 32'h0; + + 8'hf8: wb_rf_dout <= #1 ch30_conf[0] ? ch30_csr : 32'h0; + 8'hf9: wb_rf_dout <= #1 ch30_conf[0] ? ch30_txsz : 32'h0; + 8'hfa: wb_rf_dout <= #1 ch30_conf[0] ? ch30_adr0 : 32'h0; + 8'hfb: wb_rf_dout <= #1 ch30_conf[0] ? ch30_am0 : 32'h0; + 8'hfc: wb_rf_dout <= #1 ch30_conf[0] ? ch30_adr1 : 32'h0; + 8'hfd: wb_rf_dout <= #1 ch30_conf[0] ? ch30_am1 : 32'h0; + 8'hfe: wb_rf_dout <= #1 ch30_conf[0] ? pointer30 : 32'h0; + 8'hff: wb_rf_dout <= #1 ch30_conf[0] ? sw_pointer30 : 32'h0; + + endcase + + +//////////////////////////////////////////////////////////////////// +// +// WISHBONE Register Write Logic +// And DMA Engine register Update Logic +// + +// Global Registers +assign csr_we = wb_rf_we & (wb_rf_adr == 8'h0); +assign int_maska_we = wb_rf_we & (wb_rf_adr == 8'h1); +assign int_maskb_we = wb_rf_we & (wb_rf_adr == 8'h2); + +// --------------------------------------------------- + +always @(posedge clk or negedge rst) + if(!rst) csr_r <= #1 8'h0; + else + if(csr_we) csr_r <= #1 wb_rf_din[7:0]; + +// --------------------------------------------------- +// INT_MASK +always @(posedge clk or negedge rst) + if(!rst) int_maska_r <= #1 31'h0; + else + if(int_maska_we) int_maska_r <= #1 wb_rf_din[30:0]; + +always @(posedge clk or negedge rst) + if(!rst) int_maskb_r <= #1 31'h0; + else + if(int_maskb_we) int_maskb_r <= #1 wb_rf_din[30:0]; + +//////////////////////////////////////////////////////////////////// +// +// Interrupts +// + +assign int_srca = {1'b0, (int_maska_r & ch_int) }; +assign int_srcb = {1'b0, (int_maskb_r & ch_int) }; + +// Interrupt Outputs +always @(posedge clk) + inta_o <= #1 |int_srca; + +always @(posedge clk) + intb_o <= #1 |int_srcb; + +//////////////////////////////////////////////////////////////////// +// +// Channel Register File +// + +// chXX_conf = { CBUF, ED, ARS, EN } + +wb_dma_ch_rf #(0, ch0_conf[0], ch0_conf[1], ch0_conf[2], ch0_conf[3]) u0( + .clk( clk ), + .rst( rst ), + .pointer( pointer0 ), + .pointer_s( pointer0_s ), + .ch_csr( ch0_csr ), + .ch_txsz( ch0_txsz ), + .ch_adr0( ch0_adr0 ), + .ch_adr1( ch0_adr1 ), + .ch_am0( ch0_am0 ), + .ch_am1( ch0_am1 ), + .sw_pointer( sw_pointer0 ), + .ch_stop( ch_stop[0] ), + .ch_dis( ch_dis[0] ), + .int( ch_int[0] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[0] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[0] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(1, ch1_conf[0], ch1_conf[1], ch1_conf[2], ch1_conf[3]) u1( + .clk( clk ), + .rst( rst ), + .pointer( pointer1 ), + .pointer_s( pointer1_s ), + .ch_csr( ch1_csr ), + .ch_txsz( ch1_txsz ), + .ch_adr0( ch1_adr0 ), + .ch_adr1( ch1_adr1 ), + .ch_am0( ch1_am0 ), + .ch_am1( ch1_am1 ), + .sw_pointer( sw_pointer1 ), + .ch_stop( ch_stop[1] ), + .ch_dis( ch_dis[1] ), + .int( ch_int[1] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[1] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[1] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(2, ch2_conf[0], ch2_conf[1], ch2_conf[2], ch2_conf[3]) u2( + .clk( clk ), + .rst( rst ), + .pointer( pointer2 ), + .pointer_s( pointer2_s ), + .ch_csr( ch2_csr ), + .ch_txsz( ch2_txsz ), + .ch_adr0( ch2_adr0 ), + .ch_adr1( ch2_adr1 ), + .ch_am0( ch2_am0 ), + .ch_am1( ch2_am1 ), + .sw_pointer( sw_pointer2 ), + .ch_stop( ch_stop[2] ), + .ch_dis( ch_dis[2] ), + .int( ch_int[2] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[2] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[2] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(3, ch3_conf[0], ch3_conf[1], ch3_conf[2], ch3_conf[3]) u3( + .clk( clk ), + .rst( rst ), + .pointer( pointer3 ), + .pointer_s( pointer3_s ), + .ch_csr( ch3_csr ), + .ch_txsz( ch3_txsz ), + .ch_adr0( ch3_adr0 ), + .ch_adr1( ch3_adr1 ), + .ch_am0( ch3_am0 ), + .ch_am1( ch3_am1 ), + .sw_pointer( sw_pointer3 ), + .ch_stop( ch_stop[3] ), + .ch_dis( ch_dis[3] ), + .int( ch_int[3] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[3] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[3] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(4, ch4_conf[0], ch4_conf[1], ch4_conf[2], ch4_conf[3]) u4( + .clk( clk ), + .rst( rst ), + .pointer( pointer4 ), + .pointer_s( pointer4_s ), + .ch_csr( ch4_csr ), + .ch_txsz( ch4_txsz ), + .ch_adr0( ch4_adr0 ), + .ch_adr1( ch4_adr1 ), + .ch_am0( ch4_am0 ), + .ch_am1( ch4_am1 ), + .sw_pointer( sw_pointer4 ), + .ch_stop( ch_stop[4] ), + .ch_dis( ch_dis[4] ), + .int( ch_int[4] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[4] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[4] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(5, ch5_conf[0], ch5_conf[1], ch5_conf[2], ch5_conf[3]) u5( + .clk( clk ), + .rst( rst ), + .pointer( pointer5 ), + .pointer_s( pointer5_s ), + .ch_csr( ch5_csr ), + .ch_txsz( ch5_txsz ), + .ch_adr0( ch5_adr0 ), + .ch_adr1( ch5_adr1 ), + .ch_am0( ch5_am0 ), + .ch_am1( ch5_am1 ), + .sw_pointer( sw_pointer5 ), + .ch_stop( ch_stop[5] ), + .ch_dis( ch_dis[5] ), + .int( ch_int[5] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[5] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[5] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(6, ch6_conf[0], ch6_conf[1], ch6_conf[2], ch6_conf[3]) u6( + .clk( clk ), + .rst( rst ), + .pointer( pointer6 ), + .pointer_s( pointer6_s ), + .ch_csr( ch6_csr ), + .ch_txsz( ch6_txsz ), + .ch_adr0( ch6_adr0 ), + .ch_adr1( ch6_adr1 ), + .ch_am0( ch6_am0 ), + .ch_am1( ch6_am1 ), + .sw_pointer( sw_pointer6 ), + .ch_stop( ch_stop[6] ), + .ch_dis( ch_dis[6] ), + .int( ch_int[6] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[6] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[6] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(7, ch7_conf[0], ch7_conf[1], ch7_conf[2], ch7_conf[3]) u7( + .clk( clk ), + .rst( rst ), + .pointer( pointer7 ), + .pointer_s( pointer7_s ), + .ch_csr( ch7_csr ), + .ch_txsz( ch7_txsz ), + .ch_adr0( ch7_adr0 ), + .ch_adr1( ch7_adr1 ), + .ch_am0( ch7_am0 ), + .ch_am1( ch7_am1 ), + .sw_pointer( sw_pointer7 ), + .ch_stop( ch_stop[7] ), + .ch_dis( ch_dis[7] ), + .int( ch_int[7] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[7] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[7] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(8, ch8_conf[0], ch8_conf[1], ch8_conf[2], ch8_conf[3]) u8( + .clk( clk ), + .rst( rst ), + .pointer( pointer8 ), + .pointer_s( pointer8_s ), + .ch_csr( ch8_csr ), + .ch_txsz( ch8_txsz ), + .ch_adr0( ch8_adr0 ), + .ch_adr1( ch8_adr1 ), + .ch_am0( ch8_am0 ), + .ch_am1( ch8_am1 ), + .sw_pointer( sw_pointer8 ), + .ch_stop( ch_stop[8] ), + .ch_dis( ch_dis[8] ), + .int( ch_int[8] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[8] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[8] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(9, ch9_conf[0], ch9_conf[1], ch9_conf[2], ch9_conf[3]) u9( + .clk( clk ), + .rst( rst ), + .pointer( pointer9 ), + .pointer_s( pointer9_s ), + .ch_csr( ch9_csr ), + .ch_txsz( ch9_txsz ), + .ch_adr0( ch9_adr0 ), + .ch_adr1( ch9_adr1 ), + .ch_am0( ch9_am0 ), + .ch_am1( ch9_am1 ), + .sw_pointer( sw_pointer9 ), + .ch_stop( ch_stop[9] ), + .ch_dis( ch_dis[9] ), + .int( ch_int[9] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[9] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[9] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(10, ch10_conf[0], ch10_conf[1], ch10_conf[2], ch10_conf[3]) u10( + .clk( clk ), + .rst( rst ), + .pointer( pointer10 ), + .pointer_s( pointer10_s ), + .ch_csr( ch10_csr ), + .ch_txsz( ch10_txsz ), + .ch_adr0( ch10_adr0 ), + .ch_adr1( ch10_adr1 ), + .ch_am0( ch10_am0 ), + .ch_am1( ch10_am1 ), + .sw_pointer( sw_pointer10 ), + .ch_stop( ch_stop[10] ), + .ch_dis( ch_dis[10] ), + .int( ch_int[10] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[10] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[10] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(11, ch11_conf[0], ch11_conf[1], ch11_conf[2], ch11_conf[3]) u11( + .clk( clk ), + .rst( rst ), + .pointer( pointer11 ), + .pointer_s( pointer11_s ), + .ch_csr( ch11_csr ), + .ch_txsz( ch11_txsz ), + .ch_adr0( ch11_adr0 ), + .ch_adr1( ch11_adr1 ), + .ch_am0( ch11_am0 ), + .ch_am1( ch11_am1 ), + .sw_pointer( sw_pointer11 ), + .ch_stop( ch_stop[11] ), + .ch_dis( ch_dis[11] ), + .int( ch_int[11] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[11] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[11] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(12, ch12_conf[0], ch12_conf[1], ch12_conf[2], ch12_conf[3]) u12( + .clk( clk ), + .rst( rst ), + .pointer( pointer12 ), + .pointer_s( pointer12_s ), + .ch_csr( ch12_csr ), + .ch_txsz( ch12_txsz ), + .ch_adr0( ch12_adr0 ), + .ch_adr1( ch12_adr1 ), + .ch_am0( ch12_am0 ), + .ch_am1( ch12_am1 ), + .sw_pointer( sw_pointer12 ), + .ch_stop( ch_stop[12] ), + .ch_dis( ch_dis[12] ), + .int( ch_int[12] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[12] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[12] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(13, ch13_conf[0], ch13_conf[1], ch13_conf[2], ch13_conf[3]) u13( + .clk( clk ), + .rst( rst ), + .pointer( pointer13 ), + .pointer_s( pointer13_s ), + .ch_csr( ch13_csr ), + .ch_txsz( ch13_txsz ), + .ch_adr0( ch13_adr0 ), + .ch_adr1( ch13_adr1 ), + .ch_am0( ch13_am0 ), + .ch_am1( ch13_am1 ), + .sw_pointer( sw_pointer13 ), + .ch_stop( ch_stop[13] ), + .ch_dis( ch_dis[13] ), + .int( ch_int[13] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[13] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[13] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(14, ch14_conf[0], ch14_conf[1], ch14_conf[2], ch14_conf[3]) u14( + .clk( clk ), + .rst( rst ), + .pointer( pointer14 ), + .pointer_s( pointer14_s ), + .ch_csr( ch14_csr ), + .ch_txsz( ch14_txsz ), + .ch_adr0( ch14_adr0 ), + .ch_adr1( ch14_adr1 ), + .ch_am0( ch14_am0 ), + .ch_am1( ch14_am1 ), + .sw_pointer( sw_pointer14 ), + .ch_stop( ch_stop[14] ), + .ch_dis( ch_dis[14] ), + .int( ch_int[14] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[14] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[14] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(15, ch15_conf[0], ch15_conf[1], ch15_conf[2], ch15_conf[3]) u15( + .clk( clk ), + .rst( rst ), + .pointer( pointer15 ), + .pointer_s( pointer15_s ), + .ch_csr( ch15_csr ), + .ch_txsz( ch15_txsz ), + .ch_adr0( ch15_adr0 ), + .ch_adr1( ch15_adr1 ), + .ch_am0( ch15_am0 ), + .ch_am1( ch15_am1 ), + .sw_pointer( sw_pointer15 ), + .ch_stop( ch_stop[15] ), + .ch_dis( ch_dis[15] ), + .int( ch_int[15] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[15] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[15] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(16, ch16_conf[0], ch16_conf[1], ch16_conf[2], ch16_conf[3]) u16( + .clk( clk ), + .rst( rst ), + .pointer( pointer16 ), + .pointer_s( pointer16_s ), + .ch_csr( ch16_csr ), + .ch_txsz( ch16_txsz ), + .ch_adr0( ch16_adr0 ), + .ch_adr1( ch16_adr1 ), + .ch_am0( ch16_am0 ), + .ch_am1( ch16_am1 ), + .sw_pointer( sw_pointer16 ), + .ch_stop( ch_stop[16] ), + .ch_dis( ch_dis[16] ), + .int( ch_int[16] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[16] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[16] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(17, ch17_conf[0], ch17_conf[1], ch17_conf[2], ch17_conf[3]) u17( + .clk( clk ), + .rst( rst ), + .pointer( pointer17 ), + .pointer_s( pointer17_s ), + .ch_csr( ch17_csr ), + .ch_txsz( ch17_txsz ), + .ch_adr0( ch17_adr0 ), + .ch_adr1( ch17_adr1 ), + .ch_am0( ch17_am0 ), + .ch_am1( ch17_am1 ), + .sw_pointer( sw_pointer17 ), + .ch_stop( ch_stop[17] ), + .ch_dis( ch_dis[17] ), + .int( ch_int[17] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[17] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[17] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(18, ch18_conf[0], ch18_conf[1], ch18_conf[2], ch18_conf[3]) u18( + .clk( clk ), + .rst( rst ), + .pointer( pointer18 ), + .pointer_s( pointer18_s ), + .ch_csr( ch18_csr ), + .ch_txsz( ch18_txsz ), + .ch_adr0( ch18_adr0 ), + .ch_adr1( ch18_adr1 ), + .ch_am0( ch18_am0 ), + .ch_am1( ch18_am1 ), + .sw_pointer( sw_pointer18 ), + .ch_stop( ch_stop[18] ), + .ch_dis( ch_dis[18] ), + .int( ch_int[18] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[18] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[18] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(19, ch19_conf[0], ch19_conf[1], ch19_conf[2], ch19_conf[3]) u19( + .clk( clk ), + .rst( rst ), + .pointer( pointer19 ), + .pointer_s( pointer19_s ), + .ch_csr( ch19_csr ), + .ch_txsz( ch19_txsz ), + .ch_adr0( ch19_adr0 ), + .ch_adr1( ch19_adr1 ), + .ch_am0( ch19_am0 ), + .ch_am1( ch19_am1 ), + .sw_pointer( sw_pointer19 ), + .ch_stop( ch_stop[19] ), + .ch_dis( ch_dis[19] ), + .int( ch_int[19] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[19] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[19] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(20, ch20_conf[0], ch20_conf[1], ch20_conf[2], ch20_conf[3]) u20( + .clk( clk ), + .rst( rst ), + .pointer( pointer20 ), + .pointer_s( pointer20_s ), + .ch_csr( ch20_csr ), + .ch_txsz( ch20_txsz ), + .ch_adr0( ch20_adr0 ), + .ch_adr1( ch20_adr1 ), + .ch_am0( ch20_am0 ), + .ch_am1( ch20_am1 ), + .sw_pointer( sw_pointer20 ), + .ch_stop( ch_stop[20] ), + .ch_dis( ch_dis[20] ), + .int( ch_int[20] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[20] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[20] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(21, ch21_conf[0], ch21_conf[1], ch21_conf[2], ch21_conf[3]) u21( + .clk( clk ), + .rst( rst ), + .pointer( pointer21 ), + .pointer_s( pointer21_s ), + .ch_csr( ch21_csr ), + .ch_txsz( ch21_txsz ), + .ch_adr0( ch21_adr0 ), + .ch_adr1( ch21_adr1 ), + .ch_am0( ch21_am0 ), + .ch_am1( ch21_am1 ), + .sw_pointer( sw_pointer21 ), + .ch_stop( ch_stop[21] ), + .ch_dis( ch_dis[21] ), + .int( ch_int[21] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[21] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[21] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(22, ch22_conf[0], ch22_conf[1], ch22_conf[2], ch22_conf[3]) u22( + .clk( clk ), + .rst( rst ), + .pointer( pointer22 ), + .pointer_s( pointer22_s ), + .ch_csr( ch22_csr ), + .ch_txsz( ch22_txsz ), + .ch_adr0( ch22_adr0 ), + .ch_adr1( ch22_adr1 ), + .ch_am0( ch22_am0 ), + .ch_am1( ch22_am1 ), + .sw_pointer( sw_pointer22 ), + .ch_stop( ch_stop[22] ), + .ch_dis( ch_dis[22] ), + .int( ch_int[22] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[22] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[22] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(23, ch23_conf[0], ch23_conf[1], ch23_conf[2], ch23_conf[3]) u23( + .clk( clk ), + .rst( rst ), + .pointer( pointer23 ), + .pointer_s( pointer23_s ), + .ch_csr( ch23_csr ), + .ch_txsz( ch23_txsz ), + .ch_adr0( ch23_adr0 ), + .ch_adr1( ch23_adr1 ), + .ch_am0( ch23_am0 ), + .ch_am1( ch23_am1 ), + .sw_pointer( sw_pointer23 ), + .ch_stop( ch_stop[23] ), + .ch_dis( ch_dis[23] ), + .int( ch_int[23] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[23] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[23] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(24, ch24_conf[0], ch24_conf[1], ch24_conf[2], ch24_conf[3]) u24( + .clk( clk ), + .rst( rst ), + .pointer( pointer24 ), + .pointer_s( pointer24_s ), + .ch_csr( ch24_csr ), + .ch_txsz( ch24_txsz ), + .ch_adr0( ch24_adr0 ), + .ch_adr1( ch24_adr1 ), + .ch_am0( ch24_am0 ), + .ch_am1( ch24_am1 ), + .sw_pointer( sw_pointer24 ), + .ch_stop( ch_stop[24] ), + .ch_dis( ch_dis[24] ), + .int( ch_int[24] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[24] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[24] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(25, ch25_conf[0], ch25_conf[1], ch25_conf[2], ch25_conf[3]) u25( + .clk( clk ), + .rst( rst ), + .pointer( pointer25 ), + .pointer_s( pointer25_s ), + .ch_csr( ch25_csr ), + .ch_txsz( ch25_txsz ), + .ch_adr0( ch25_adr0 ), + .ch_adr1( ch25_adr1 ), + .ch_am0( ch25_am0 ), + .ch_am1( ch25_am1 ), + .sw_pointer( sw_pointer25 ), + .ch_stop( ch_stop[25] ), + .ch_dis( ch_dis[25] ), + .int( ch_int[25] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[25] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[25] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(26, ch26_conf[0], ch26_conf[1], ch26_conf[2], ch26_conf[3]) u26( + .clk( clk ), + .rst( rst ), + .pointer( pointer26 ), + .pointer_s( pointer26_s ), + .ch_csr( ch26_csr ), + .ch_txsz( ch26_txsz ), + .ch_adr0( ch26_adr0 ), + .ch_adr1( ch26_adr1 ), + .ch_am0( ch26_am0 ), + .ch_am1( ch26_am1 ), + .sw_pointer( sw_pointer26 ), + .ch_stop( ch_stop[26] ), + .ch_dis( ch_dis[26] ), + .int( ch_int[26] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[26] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[26] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(27, ch27_conf[0], ch27_conf[1], ch27_conf[2], ch27_conf[3]) u27( + .clk( clk ), + .rst( rst ), + .pointer( pointer27 ), + .pointer_s( pointer27_s ), + .ch_csr( ch27_csr ), + .ch_txsz( ch27_txsz ), + .ch_adr0( ch27_adr0 ), + .ch_adr1( ch27_adr1 ), + .ch_am0( ch27_am0 ), + .ch_am1( ch27_am1 ), + .sw_pointer( sw_pointer27 ), + .ch_stop( ch_stop[27] ), + .ch_dis( ch_dis[27] ), + .int( ch_int[27] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[27] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[27] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(28, ch28_conf[0], ch28_conf[1], ch28_conf[2], ch28_conf[3]) u28( + .clk( clk ), + .rst( rst ), + .pointer( pointer28 ), + .pointer_s( pointer28_s ), + .ch_csr( ch28_csr ), + .ch_txsz( ch28_txsz ), + .ch_adr0( ch28_adr0 ), + .ch_adr1( ch28_adr1 ), + .ch_am0( ch28_am0 ), + .ch_am1( ch28_am1 ), + .sw_pointer( sw_pointer28 ), + .ch_stop( ch_stop[28] ), + .ch_dis( ch_dis[28] ), + .int( ch_int[28] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[28] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[28] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(29, ch29_conf[0], ch29_conf[1], ch29_conf[2], ch29_conf[3]) u29( + .clk( clk ), + .rst( rst ), + .pointer( pointer29 ), + .pointer_s( pointer29_s ), + .ch_csr( ch29_csr ), + .ch_txsz( ch29_txsz ), + .ch_adr0( ch29_adr0 ), + .ch_adr1( ch29_adr1 ), + .ch_am0( ch29_am0 ), + .ch_am1( ch29_am1 ), + .sw_pointer( sw_pointer29 ), + .ch_stop( ch_stop[29] ), + .ch_dis( ch_dis[29] ), + .int( ch_int[29] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[29] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[29] ), + .ptr_set( ptr_set ) + ); + +wb_dma_ch_rf #(30, ch30_conf[0], ch30_conf[1], ch30_conf[2], ch30_conf[3]) u30( + .clk( clk ), + .rst( rst ), + .pointer( pointer30 ), + .pointer_s( pointer30_s ), + .ch_csr( ch30_csr ), + .ch_txsz( ch30_txsz ), + .ch_adr0( ch30_adr0 ), + .ch_adr1( ch30_adr1 ), + .ch_am0( ch30_am0 ), + .ch_am1( ch30_am1 ), + .sw_pointer( sw_pointer30 ), + .ch_stop( ch_stop[30] ), + .ch_dis( ch_dis[30] ), + .int( ch_int[30] ), + .wb_rf_din( wb_rf_din ), + .wb_rf_adr( wb_rf_adr ), + .wb_rf_we( wb_rf_we ), + .wb_rf_re( wb_rf_re ), + .ch_sel( ch_sel ), + .ndnr( ndnr[30] ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest[30] ), + .ptr_set( ptr_set ) + ); + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v new file mode 100644 index 000000000..3d6a3148b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v @@ -0,0 +1,1126 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_top.v,v 1.5 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_top.v,v $ +// Revision 1.5 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.4 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.3 2001/09/07 15:34:38 rudi +// +// Changed reset to active high. +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.3 2001/06/13 02:26:50 rudi +// +// +// Small changes after running lint. +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:23 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_top(clk_i, rst_i, + + wb0s_data_i, wb0s_data_o, wb0_addr_i, wb0_sel_i, wb0_we_i, wb0_cyc_i, + wb0_stb_i, wb0_ack_o, wb0_err_o, wb0_rty_o, + wb0m_data_i, wb0m_data_o, wb0_addr_o, wb0_sel_o, wb0_we_o, wb0_cyc_o, + wb0_stb_o, wb0_ack_i, wb0_err_i, wb0_rty_i, + + wb1s_data_i, wb1s_data_o, wb1_addr_i, wb1_sel_i, wb1_we_i, wb1_cyc_i, + wb1_stb_i, wb1_ack_o, wb1_err_o, wb1_rty_o, + wb1m_data_i, wb1m_data_o, wb1_addr_o, wb1_sel_o, wb1_we_o, wb1_cyc_o, + wb1_stb_o, wb1_ack_i, wb1_err_i, wb1_rty_i, + + dma_req_i, dma_ack_o, dma_nd_i, dma_rest_i, + + inta_o, intb_o + ); + +//////////////////////////////////////////////////////////////////// +// +// Module Parameters +// + +// chXX_conf = { CBUF, ED, ARS, EN } +parameter rf_addr = 0; +parameter [1:0] pri_sel = 2'h0; +parameter ch_count = 1; +parameter [3:0] ch0_conf = 4'h1; +parameter [3:0] ch1_conf = 4'h0; +parameter [3:0] ch2_conf = 4'h0; +parameter [3:0] ch3_conf = 4'h0; +parameter [3:0] ch4_conf = 4'h0; +parameter [3:0] ch5_conf = 4'h0; +parameter [3:0] ch6_conf = 4'h0; +parameter [3:0] ch7_conf = 4'h0; +parameter [3:0] ch8_conf = 4'h0; +parameter [3:0] ch9_conf = 4'h0; +parameter [3:0] ch10_conf = 4'h0; +parameter [3:0] ch11_conf = 4'h0; +parameter [3:0] ch12_conf = 4'h0; +parameter [3:0] ch13_conf = 4'h0; +parameter [3:0] ch14_conf = 4'h0; +parameter [3:0] ch15_conf = 4'h0; +parameter [3:0] ch16_conf = 4'h0; +parameter [3:0] ch17_conf = 4'h0; +parameter [3:0] ch18_conf = 4'h0; +parameter [3:0] ch19_conf = 4'h0; +parameter [3:0] ch20_conf = 4'h0; +parameter [3:0] ch21_conf = 4'h0; +parameter [3:0] ch22_conf = 4'h0; +parameter [3:0] ch23_conf = 4'h0; +parameter [3:0] ch24_conf = 4'h0; +parameter [3:0] ch25_conf = 4'h0; +parameter [3:0] ch26_conf = 4'h0; +parameter [3:0] ch27_conf = 4'h0; +parameter [3:0] ch28_conf = 4'h0; +parameter [3:0] ch29_conf = 4'h0; +parameter [3:0] ch30_conf = 4'h0; + +//////////////////////////////////////////////////////////////////// +// +// Module IOs +// + +input clk_i, rst_i; + +// -------------------------------------- +// WISHBONE INTERFACE 0 + +// Slave Interface +input [31:0] wb0s_data_i; +output [31:0] wb0s_data_o; +input [31:0] wb0_addr_i; +input [3:0] wb0_sel_i; +input wb0_we_i; +input wb0_cyc_i; +input wb0_stb_i; +output wb0_ack_o; +output wb0_err_o; +output wb0_rty_o; + +// Master Interface +input [31:0] wb0m_data_i; +output [31:0] wb0m_data_o; +output [31:0] wb0_addr_o; +output [3:0] wb0_sel_o; +output wb0_we_o; +output wb0_cyc_o; +output wb0_stb_o; +input wb0_ack_i; +input wb0_err_i; +input wb0_rty_i; + +// -------------------------------------- +// WISHBONE INTERFACE 1 + +// Slave Interface +input [31:0] wb1s_data_i; +output [31:0] wb1s_data_o; +input [31:0] wb1_addr_i; +input [3:0] wb1_sel_i; +input wb1_we_i; +input wb1_cyc_i; +input wb1_stb_i; +output wb1_ack_o; +output wb1_err_o; +output wb1_rty_o; + +// Master Interface +input [31:0] wb1m_data_i; +output [31:0] wb1m_data_o; +output [31:0] wb1_addr_o; +output [3:0] wb1_sel_o; +output wb1_we_o; +output wb1_cyc_o; +output wb1_stb_o; +input wb1_ack_i; +input wb1_err_i; +input wb1_rty_i; + +// -------------------------------------- +// Misc Signals +input [ch_count-1:0] dma_req_i; +input [ch_count-1:0] dma_nd_i; +output [ch_count-1:0] dma_ack_o; +input [ch_count-1:0] dma_rest_i; +output inta_o; +output intb_o; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [31:0] pointer0, pointer0_s, ch0_csr, ch0_txsz, ch0_adr0, ch0_adr1, ch0_am0, ch0_am1; +wire [31:0] pointer1, pointer1_s, ch1_csr, ch1_txsz, ch1_adr0, ch1_adr1, ch1_am0, ch1_am1; +wire [31:0] pointer2, pointer2_s, ch2_csr, ch2_txsz, ch2_adr0, ch2_adr1, ch2_am0, ch2_am1; +wire [31:0] pointer3, pointer3_s, ch3_csr, ch3_txsz, ch3_adr0, ch3_adr1, ch3_am0, ch3_am1; +wire [31:0] pointer4, pointer4_s, ch4_csr, ch4_txsz, ch4_adr0, ch4_adr1, ch4_am0, ch4_am1; +wire [31:0] pointer5, pointer5_s, ch5_csr, ch5_txsz, ch5_adr0, ch5_adr1, ch5_am0, ch5_am1; +wire [31:0] pointer6, pointer6_s, ch6_csr, ch6_txsz, ch6_adr0, ch6_adr1, ch6_am0, ch6_am1; +wire [31:0] pointer7, pointer7_s, ch7_csr, ch7_txsz, ch7_adr0, ch7_adr1, ch7_am0, ch7_am1; +wire [31:0] pointer8, pointer8_s, ch8_csr, ch8_txsz, ch8_adr0, ch8_adr1, ch8_am0, ch8_am1; +wire [31:0] pointer9, pointer9_s, ch9_csr, ch9_txsz, ch9_adr0, ch9_adr1, ch9_am0, ch9_am1; +wire [31:0] pointer10, pointer10_s, ch10_csr, ch10_txsz, ch10_adr0, ch10_adr1, ch10_am0, ch10_am1; +wire [31:0] pointer11, pointer11_s, ch11_csr, ch11_txsz, ch11_adr0, ch11_adr1, ch11_am0, ch11_am1; +wire [31:0] pointer12, pointer12_s, ch12_csr, ch12_txsz, ch12_adr0, ch12_adr1, ch12_am0, ch12_am1; +wire [31:0] pointer13, pointer13_s, ch13_csr, ch13_txsz, ch13_adr0, ch13_adr1, ch13_am0, ch13_am1; +wire [31:0] pointer14, pointer14_s, ch14_csr, ch14_txsz, ch14_adr0, ch14_adr1, ch14_am0, ch14_am1; +wire [31:0] pointer15, pointer15_s, ch15_csr, ch15_txsz, ch15_adr0, ch15_adr1, ch15_am0, ch15_am1; +wire [31:0] pointer16, pointer16_s, ch16_csr, ch16_txsz, ch16_adr0, ch16_adr1, ch16_am0, ch16_am1; +wire [31:0] pointer17, pointer17_s, ch17_csr, ch17_txsz, ch17_adr0, ch17_adr1, ch17_am0, ch17_am1; +wire [31:0] pointer18, pointer18_s, ch18_csr, ch18_txsz, ch18_adr0, ch18_adr1, ch18_am0, ch18_am1; +wire [31:0] pointer19, pointer19_s, ch19_csr, ch19_txsz, ch19_adr0, ch19_adr1, ch19_am0, ch19_am1; +wire [31:0] pointer20, pointer20_s, ch20_csr, ch20_txsz, ch20_adr0, ch20_adr1, ch20_am0, ch20_am1; +wire [31:0] pointer21, pointer21_s, ch21_csr, ch21_txsz, ch21_adr0, ch21_adr1, ch21_am0, ch21_am1; +wire [31:0] pointer22, pointer22_s, ch22_csr, ch22_txsz, ch22_adr0, ch22_adr1, ch22_am0, ch22_am1; +wire [31:0] pointer23, pointer23_s, ch23_csr, ch23_txsz, ch23_adr0, ch23_adr1, ch23_am0, ch23_am1; +wire [31:0] pointer24, pointer24_s, ch24_csr, ch24_txsz, ch24_adr0, ch24_adr1, ch24_am0, ch24_am1; +wire [31:0] pointer25, pointer25_s, ch25_csr, ch25_txsz, ch25_adr0, ch25_adr1, ch25_am0, ch25_am1; +wire [31:0] pointer26, pointer26_s, ch26_csr, ch26_txsz, ch26_adr0, ch26_adr1, ch26_am0, ch26_am1; +wire [31:0] pointer27, pointer27_s, ch27_csr, ch27_txsz, ch27_adr0, ch27_adr1, ch27_am0, ch27_am1; +wire [31:0] pointer28, pointer28_s, ch28_csr, ch28_txsz, ch28_adr0, ch28_adr1, ch28_am0, ch28_am1; +wire [31:0] pointer29, pointer29_s, ch29_csr, ch29_txsz, ch29_adr0, ch29_adr1, ch29_am0, ch29_am1; +wire [31:0] pointer30, pointer30_s, ch30_csr, ch30_txsz, ch30_adr0, ch30_adr1, ch30_am0, ch30_am1; + +wire [4:0] ch_sel; // Write Back Channel Select +wire [30:0] ndnr; // Next Descriptor No Request +wire de_start; // Start DMA Engine +wire ndr; // Next Descriptor With Request +wire [31:0] csr; // Selected Channel CSR +wire [31:0] pointer; +wire [31:0] pointer_s; +wire [31:0] txsz; // Selected Channel Transfer Size +wire [31:0] adr0, adr1; // Selected Channel Addresses +wire [31:0] am0, am1; // Selected Channel Address Masks +wire next_ch; // Indicates the DMA Engine is done + +wire inta_o, intb_o; +wire dma_abort; +wire dma_busy, dma_err, dma_done, dma_done_all; +wire [31:0] de_csr; +wire [11:0] de_txsz; +wire [31:0] de_adr0; +wire [31:0] de_adr1; +wire de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we; +wire de_fetch_descr; +wire ptr_set; +wire de_ack; +wire pause_req; +wire paused; + +wire mast0_go; // Perform a Master Cycle (as long as this +wire mast0_we; // Read/Write +wire [31:0] mast0_adr; // Address for the transfer +wire [31:0] mast0_din; // Internal Input Data +wire [31:0] mast0_dout; // Internal Output Data +wire mast0_err; // Indicates an error has occurred +wire mast0_drdy; // Indicated that either data is available +wire mast0_wait; // Tells the master to insert wait cycles + +wire [31:0] slv0_adr; // Slave Address +wire [31:0] slv0_din; // Slave Input Data +wire [31:0] slv0_dout; // Slave Output Data +wire slv0_re; // Slave Read Enable +wire slv0_we; // Slave Write Enable + +wire pt0_sel_i; // Pass Through Mode Selected +wire [70:0] mast0_pt_in; // Grouped WISHBONE inputs +wire [34:0] mast0_pt_out; // Grouped WISHBONE outputs + +wire pt0_sel_o; // Pass Through Mode Active +wire [70:0] slv0_pt_out; // Grouped WISHBONE out signals +wire [34:0] slv0_pt_in; // Grouped WISHBONE in signals + +wire mast1_go; // Perform a Master Cycle (as long as this +wire mast1_we; // Read/Write +wire [31:0] mast1_adr; // Address for the transfer +wire [31:0] mast1_din; // Internal Input Data +wire [31:0] mast1_dout; // Internal Output Data +wire mast1_err; // Indicates an error has occurred +wire mast1_drdy; // Indicated that either data is available +wire mast1_wait; // Tells the master to insert wait cycles + +wire [31:0] slv1_adr; // Slave Address +wire [31:0] slv1_dout; // Slave Output Data +wire slv1_re; // Slave Read Enable +wire slv1_we; // Slave Write Enable + +wire pt1_sel_i; // Pass Through Mode Selected +wire [70:0] mast1_pt_in; // Grouped WISHBONE inputs +wire [34:0] mast1_pt_out; // Grouped WISHBONE outputs + +wire pt1_sel_o; // Pass Through Mode Active +wire [70:0] slv1_pt_out; // Grouped WISHBONE out signals +wire [34:0] slv1_pt_in; // Grouped WISHBONE in signals + +wire [30:0] dma_req; +wire [30:0] dma_nd; +wire [30:0] dma_ack; +wire [30:0] dma_rest; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +wire [31:0] tmp_gnd = 32'h0; + +assign dma_req[ch_count-1:0] = dma_req_i; +assign dma_nd[ch_count-1:0] = dma_nd_i; +assign dma_rest[ch_count-1:0] = dma_rest_i; +assign dma_ack_o = {tmp_gnd[31-ch_count:0], dma_ack[ch_count-1:0]}; + +// -------------------------------------------------- +// This should go in to a separate Pass Through Block +assign pt1_sel_i = pt0_sel_o; +assign pt0_sel_i = pt1_sel_o; +assign mast1_pt_in = slv0_pt_out; +assign slv0_pt_in = mast1_pt_out; +assign mast0_pt_in = slv1_pt_out; +assign slv1_pt_in = mast0_pt_out; +// -------------------------------------------------- + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +// DMA Register File +wb_dma_rf #( ch0_conf, + ch1_conf, + ch2_conf, + ch3_conf, + ch4_conf, + ch5_conf, + ch6_conf, + ch7_conf, + ch8_conf, + ch9_conf, + ch10_conf, + ch11_conf, + ch12_conf, + ch13_conf, + ch14_conf, + ch15_conf, + ch16_conf, + ch17_conf, + ch18_conf, + ch19_conf, + ch20_conf, + ch21_conf, + ch22_conf, + ch23_conf, + ch24_conf, + ch25_conf, + ch26_conf, + ch27_conf, + ch28_conf, + ch29_conf, + ch30_conf) + u0( + .clk( clk_i ), + .rst( ~rst_i ), + .wb_rf_adr( slv0_adr[9:2] ), + .wb_rf_din( slv0_dout ), + .wb_rf_dout( slv0_din ), + .wb_rf_re( slv0_re ), + .wb_rf_we( slv0_we ), + .inta_o( inta_o ), + .intb_o( intb_o ), + .pointer0( pointer0 ), + .pointer0_s( pointer0_s ), + .ch0_csr( ch0_csr ), + .ch0_txsz( ch0_txsz ), + .ch0_adr0( ch0_adr0 ), + .ch0_adr1( ch0_adr1 ), + .ch0_am0( ch0_am0 ), + .ch0_am1( ch0_am1 ), + .pointer1( pointer1 ), + .pointer1_s( pointer1_s ), + .ch1_csr( ch1_csr ), + .ch1_txsz( ch1_txsz ), + .ch1_adr0( ch1_adr0 ), + .ch1_adr1( ch1_adr1 ), + .ch1_am0( ch1_am0 ), + .ch1_am1( ch1_am1 ), + .pointer2( pointer2 ), + .pointer2_s( pointer2_s ), + .ch2_csr( ch2_csr ), + .ch2_txsz( ch2_txsz ), + .ch2_adr0( ch2_adr0 ), + .ch2_adr1( ch2_adr1 ), + .ch2_am0( ch2_am0 ), + .ch2_am1( ch2_am1 ), + .pointer3( pointer3 ), + .pointer3_s( pointer3_s ), + .ch3_csr( ch3_csr ), + .ch3_txsz( ch3_txsz ), + .ch3_adr0( ch3_adr0 ), + .ch3_adr1( ch3_adr1 ), + .ch3_am0( ch3_am0 ), + .ch3_am1( ch3_am1 ), + .pointer4( pointer4 ), + .pointer4_s( pointer4_s ), + .ch4_csr( ch4_csr ), + .ch4_txsz( ch4_txsz ), + .ch4_adr0( ch4_adr0 ), + .ch4_adr1( ch4_adr1 ), + .ch4_am0( ch4_am0 ), + .ch4_am1( ch4_am1 ), + .pointer5( pointer5 ), + .pointer5_s( pointer5_s ), + .ch5_csr( ch5_csr ), + .ch5_txsz( ch5_txsz ), + .ch5_adr0( ch5_adr0 ), + .ch5_adr1( ch5_adr1 ), + .ch5_am0( ch5_am0 ), + .ch5_am1( ch5_am1 ), + .pointer6( pointer6 ), + .pointer6_s( pointer6_s ), + .ch6_csr( ch6_csr ), + .ch6_txsz( ch6_txsz ), + .ch6_adr0( ch6_adr0 ), + .ch6_adr1( ch6_adr1 ), + .ch6_am0( ch6_am0 ), + .ch6_am1( ch6_am1 ), + .pointer7( pointer7 ), + .pointer7_s( pointer7_s ), + .ch7_csr( ch7_csr ), + .ch7_txsz( ch7_txsz ), + .ch7_adr0( ch7_adr0 ), + .ch7_adr1( ch7_adr1 ), + .ch7_am0( ch7_am0 ), + .ch7_am1( ch7_am1 ), + .pointer8( pointer8 ), + .pointer8_s( pointer8_s ), + .ch8_csr( ch8_csr ), + .ch8_txsz( ch8_txsz ), + .ch8_adr0( ch8_adr0 ), + .ch8_adr1( ch8_adr1 ), + .ch8_am0( ch8_am0 ), + .ch8_am1( ch8_am1 ), + .pointer9( pointer9 ), + .pointer9_s( pointer9_s ), + .ch9_csr( ch9_csr ), + .ch9_txsz( ch9_txsz ), + .ch9_adr0( ch9_adr0 ), + .ch9_adr1( ch9_adr1 ), + .ch9_am0( ch9_am0 ), + .ch9_am1( ch9_am1 ), + .pointer10( pointer10 ), + .pointer10_s( pointer10_s ), + .ch10_csr( ch10_csr ), + .ch10_txsz( ch10_txsz ), + .ch10_adr0( ch10_adr0 ), + .ch10_adr1( ch10_adr1 ), + .ch10_am0( ch10_am0 ), + .ch10_am1( ch10_am1 ), + .pointer11( pointer11 ), + .pointer11_s( pointer11_s ), + .ch11_csr( ch11_csr ), + .ch11_txsz( ch11_txsz ), + .ch11_adr0( ch11_adr0 ), + .ch11_adr1( ch11_adr1 ), + .ch11_am0( ch11_am0 ), + .ch11_am1( ch11_am1 ), + .pointer12( pointer12 ), + .pointer12_s( pointer12_s ), + .ch12_csr( ch12_csr ), + .ch12_txsz( ch12_txsz ), + .ch12_adr0( ch12_adr0 ), + .ch12_adr1( ch12_adr1 ), + .ch12_am0( ch12_am0 ), + .ch12_am1( ch12_am1 ), + .pointer13( pointer13 ), + .pointer13_s( pointer13_s ), + .ch13_csr( ch13_csr ), + .ch13_txsz( ch13_txsz ), + .ch13_adr0( ch13_adr0 ), + .ch13_adr1( ch13_adr1 ), + .ch13_am0( ch13_am0 ), + .ch13_am1( ch13_am1 ), + .pointer14( pointer14 ), + .pointer14_s( pointer14_s ), + .ch14_csr( ch14_csr ), + .ch14_txsz( ch14_txsz ), + .ch14_adr0( ch14_adr0 ), + .ch14_adr1( ch14_adr1 ), + .ch14_am0( ch14_am0 ), + .ch14_am1( ch14_am1 ), + .pointer15( pointer15 ), + .pointer15_s( pointer15_s ), + .ch15_csr( ch15_csr ), + .ch15_txsz( ch15_txsz ), + .ch15_adr0( ch15_adr0 ), + .ch15_adr1( ch15_adr1 ), + .ch15_am0( ch15_am0 ), + .ch15_am1( ch15_am1 ), + .pointer16( pointer16 ), + .pointer16_s( pointer16_s ), + .ch16_csr( ch16_csr ), + .ch16_txsz( ch16_txsz ), + .ch16_adr0( ch16_adr0 ), + .ch16_adr1( ch16_adr1 ), + .ch16_am0( ch16_am0 ), + .ch16_am1( ch16_am1 ), + .pointer17( pointer17 ), + .pointer17_s( pointer17_s ), + .ch17_csr( ch17_csr ), + .ch17_txsz( ch17_txsz ), + .ch17_adr0( ch17_adr0 ), + .ch17_adr1( ch17_adr1 ), + .ch17_am0( ch17_am0 ), + .ch17_am1( ch17_am1 ), + .pointer18( pointer18 ), + .pointer18_s( pointer18_s ), + .ch18_csr( ch18_csr ), + .ch18_txsz( ch18_txsz ), + .ch18_adr0( ch18_adr0 ), + .ch18_adr1( ch18_adr1 ), + .ch18_am0( ch18_am0 ), + .ch18_am1( ch18_am1 ), + .pointer19( pointer19 ), + .pointer19_s( pointer19_s ), + .ch19_csr( ch19_csr ), + .ch19_txsz( ch19_txsz ), + .ch19_adr0( ch19_adr0 ), + .ch19_adr1( ch19_adr1 ), + .ch19_am0( ch19_am0 ), + .ch19_am1( ch19_am1 ), + .pointer20( pointer20 ), + .pointer20_s( pointer20_s ), + .ch20_csr( ch20_csr ), + .ch20_txsz( ch20_txsz ), + .ch20_adr0( ch20_adr0 ), + .ch20_adr1( ch20_adr1 ), + .ch20_am0( ch20_am0 ), + .ch20_am1( ch20_am1 ), + .pointer21( pointer21 ), + .pointer21_s( pointer21_s ), + .ch21_csr( ch21_csr ), + .ch21_txsz( ch21_txsz ), + .ch21_adr0( ch21_adr0 ), + .ch21_adr1( ch21_adr1 ), + .ch21_am0( ch21_am0 ), + .ch21_am1( ch21_am1 ), + .pointer22( pointer22 ), + .pointer22_s( pointer22_s ), + .ch22_csr( ch22_csr ), + .ch22_txsz( ch22_txsz ), + .ch22_adr0( ch22_adr0 ), + .ch22_adr1( ch22_adr1 ), + .ch22_am0( ch22_am0 ), + .ch22_am1( ch22_am1 ), + .pointer23( pointer23 ), + .pointer23_s( pointer23_s ), + .ch23_csr( ch23_csr ), + .ch23_txsz( ch23_txsz ), + .ch23_adr0( ch23_adr0 ), + .ch23_adr1( ch23_adr1 ), + .ch23_am0( ch23_am0 ), + .ch23_am1( ch23_am1 ), + .pointer24( pointer24 ), + .pointer24_s( pointer24_s ), + .ch24_csr( ch24_csr ), + .ch24_txsz( ch24_txsz ), + .ch24_adr0( ch24_adr0 ), + .ch24_adr1( ch24_adr1 ), + .ch24_am0( ch24_am0 ), + .ch24_am1( ch24_am1 ), + .pointer25( pointer25 ), + .pointer25_s( pointer25_s ), + .ch25_csr( ch25_csr ), + .ch25_txsz( ch25_txsz ), + .ch25_adr0( ch25_adr0 ), + .ch25_adr1( ch25_adr1 ), + .ch25_am0( ch25_am0 ), + .ch25_am1( ch25_am1 ), + .pointer26( pointer26 ), + .pointer26_s( pointer26_s ), + .ch26_csr( ch26_csr ), + .ch26_txsz( ch26_txsz ), + .ch26_adr0( ch26_adr0 ), + .ch26_adr1( ch26_adr1 ), + .ch26_am0( ch26_am0 ), + .ch26_am1( ch26_am1 ), + .pointer27( pointer27 ), + .pointer27_s( pointer27_s ), + .ch27_csr( ch27_csr ), + .ch27_txsz( ch27_txsz ), + .ch27_adr0( ch27_adr0 ), + .ch27_adr1( ch27_adr1 ), + .ch27_am0( ch27_am0 ), + .ch27_am1( ch27_am1 ), + .pointer28( pointer28 ), + .pointer28_s( pointer28_s ), + .ch28_csr( ch28_csr ), + .ch28_txsz( ch28_txsz ), + .ch28_adr0( ch28_adr0 ), + .ch28_adr1( ch28_adr1 ), + .ch28_am0( ch28_am0 ), + .ch28_am1( ch28_am1 ), + .pointer29( pointer29 ), + .pointer29_s( pointer29_s ), + .ch29_csr( ch29_csr ), + .ch29_txsz( ch29_txsz ), + .ch29_adr0( ch29_adr0 ), + .ch29_adr1( ch29_adr1 ), + .ch29_am0( ch29_am0 ), + .ch29_am1( ch29_am1 ), + .pointer30( pointer30 ), + .pointer30_s( pointer30_s ), + .ch30_csr( ch30_csr ), + .ch30_txsz( ch30_txsz ), + .ch30_adr0( ch30_adr0 ), + .ch30_adr1( ch30_adr1 ), + .ch30_am0( ch30_am0 ), + .ch30_am1( ch30_am1 ), + .ch_sel( ch_sel ), + .ndnr( ndnr ), + .pause_req( pause_req ), + .paused( paused ), + .dma_abort( dma_abort ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .dma_rest( dma_rest ), + .ptr_set( ptr_set ) + ); + +// Channel Select +wb_dma_ch_sel #(pri_sel, + ch0_conf, + ch1_conf, + ch2_conf, + ch3_conf, + ch4_conf, + ch5_conf, + ch6_conf, + ch7_conf, + ch8_conf, + ch9_conf, + ch10_conf, + ch11_conf, + ch12_conf, + ch13_conf, + ch14_conf, + ch15_conf, + ch16_conf, + ch17_conf, + ch18_conf, + ch19_conf, + ch20_conf, + ch21_conf, + ch22_conf, + ch23_conf, + ch24_conf, + ch25_conf, + ch26_conf, + ch27_conf, + ch28_conf, + ch29_conf, + ch30_conf) + u1( + .clk( clk_i ), + .rst( ~rst_i ), + .req_i( dma_req ), + .ack_o( dma_ack ), + .nd_i( dma_nd ), + + .pointer0( pointer0 ), + .pointer0_s( pointer0_s ), + .ch0_csr( ch0_csr ), + .ch0_txsz( ch0_txsz ), + .ch0_adr0( ch0_adr0 ), + .ch0_adr1( ch0_adr1 ), + .ch0_am0( ch0_am0 ), + .ch0_am1( ch0_am1 ), + .pointer1( pointer1 ), + .pointer1_s( pointer1_s ), + .ch1_csr( ch1_csr ), + .ch1_txsz( ch1_txsz ), + .ch1_adr0( ch1_adr0 ), + .ch1_adr1( ch1_adr1 ), + .ch1_am0( ch1_am0 ), + .ch1_am1( ch1_am1 ), + .pointer2( pointer2 ), + .pointer2_s( pointer2_s ), + .ch2_csr( ch2_csr ), + .ch2_txsz( ch2_txsz ), + .ch2_adr0( ch2_adr0 ), + .ch2_adr1( ch2_adr1 ), + .ch2_am0( ch2_am0 ), + .ch2_am1( ch2_am1 ), + .pointer3( pointer3 ), + .pointer3_s( pointer3_s ), + .ch3_csr( ch3_csr ), + .ch3_txsz( ch3_txsz ), + .ch3_adr0( ch3_adr0 ), + .ch3_adr1( ch3_adr1 ), + .ch3_am0( ch3_am0 ), + .ch3_am1( ch3_am1 ), + .pointer4( pointer4 ), + .pointer4_s( pointer4_s ), + .ch4_csr( ch4_csr ), + .ch4_txsz( ch4_txsz ), + .ch4_adr0( ch4_adr0 ), + .ch4_adr1( ch4_adr1 ), + .ch4_am0( ch4_am0 ), + .ch4_am1( ch4_am1 ), + .pointer5( pointer5 ), + .pointer5_s( pointer5_s ), + .ch5_csr( ch5_csr ), + .ch5_txsz( ch5_txsz ), + .ch5_adr0( ch5_adr0 ), + .ch5_adr1( ch5_adr1 ), + .ch5_am0( ch5_am0 ), + .ch5_am1( ch5_am1 ), + .pointer6( pointer6 ), + .pointer6_s( pointer6_s ), + .ch6_csr( ch6_csr ), + .ch6_txsz( ch6_txsz ), + .ch6_adr0( ch6_adr0 ), + .ch6_adr1( ch6_adr1 ), + .ch6_am0( ch6_am0 ), + .ch6_am1( ch6_am1 ), + .pointer7( pointer7 ), + .pointer7_s( pointer7_s ), + .ch7_csr( ch7_csr ), + .ch7_txsz( ch7_txsz ), + .ch7_adr0( ch7_adr0 ), + .ch7_adr1( ch7_adr1 ), + .ch7_am0( ch7_am0 ), + .ch7_am1( ch7_am1 ), + .pointer8( pointer8 ), + .pointer8_s( pointer8_s ), + .ch8_csr( ch8_csr ), + .ch8_txsz( ch8_txsz ), + .ch8_adr0( ch8_adr0 ), + .ch8_adr1( ch8_adr1 ), + .ch8_am0( ch8_am0 ), + .ch8_am1( ch8_am1 ), + .pointer9( pointer9 ), + .pointer9_s( pointer9_s ), + .ch9_csr( ch9_csr ), + .ch9_txsz( ch9_txsz ), + .ch9_adr0( ch9_adr0 ), + .ch9_adr1( ch9_adr1 ), + .ch9_am0( ch9_am0 ), + .ch9_am1( ch9_am1 ), + .pointer10( pointer10 ), + .pointer10_s( pointer10_s ), + .ch10_csr( ch10_csr ), + .ch10_txsz( ch10_txsz ), + .ch10_adr0( ch10_adr0 ), + .ch10_adr1( ch10_adr1 ), + .ch10_am0( ch10_am0 ), + .ch10_am1( ch10_am1 ), + .pointer11( pointer11 ), + .pointer11_s( pointer11_s ), + .ch11_csr( ch11_csr ), + .ch11_txsz( ch11_txsz ), + .ch11_adr0( ch11_adr0 ), + .ch11_adr1( ch11_adr1 ), + .ch11_am0( ch11_am0 ), + .ch11_am1( ch11_am1 ), + .pointer12( pointer12 ), + .pointer12_s( pointer12_s ), + .ch12_csr( ch12_csr ), + .ch12_txsz( ch12_txsz ), + .ch12_adr0( ch12_adr0 ), + .ch12_adr1( ch12_adr1 ), + .ch12_am0( ch12_am0 ), + .ch12_am1( ch12_am1 ), + .pointer13( pointer13 ), + .pointer13_s( pointer13_s ), + .ch13_csr( ch13_csr ), + .ch13_txsz( ch13_txsz ), + .ch13_adr0( ch13_adr0 ), + .ch13_adr1( ch13_adr1 ), + .ch13_am0( ch13_am0 ), + .ch13_am1( ch13_am1 ), + .pointer14( pointer14 ), + .pointer14_s( pointer14_s ), + .ch14_csr( ch14_csr ), + .ch14_txsz( ch14_txsz ), + .ch14_adr0( ch14_adr0 ), + .ch14_adr1( ch14_adr1 ), + .ch14_am0( ch14_am0 ), + .ch14_am1( ch14_am1 ), + .pointer15( pointer15 ), + .pointer15_s( pointer15_s ), + .ch15_csr( ch15_csr ), + .ch15_txsz( ch15_txsz ), + .ch15_adr0( ch15_adr0 ), + .ch15_adr1( ch15_adr1 ), + .ch15_am0( ch15_am0 ), + .ch15_am1( ch15_am1 ), + .pointer16( pointer16 ), + .pointer16_s( pointer16_s ), + .ch16_csr( ch16_csr ), + .ch16_txsz( ch16_txsz ), + .ch16_adr0( ch16_adr0 ), + .ch16_adr1( ch16_adr1 ), + .ch16_am0( ch16_am0 ), + .ch16_am1( ch16_am1 ), + .pointer17( pointer17 ), + .pointer17_s( pointer17_s ), + .ch17_csr( ch17_csr ), + .ch17_txsz( ch17_txsz ), + .ch17_adr0( ch17_adr0 ), + .ch17_adr1( ch17_adr1 ), + .ch17_am0( ch17_am0 ), + .ch17_am1( ch17_am1 ), + .pointer18( pointer18 ), + .pointer18_s( pointer18_s ), + .ch18_csr( ch18_csr ), + .ch18_txsz( ch18_txsz ), + .ch18_adr0( ch18_adr0 ), + .ch18_adr1( ch18_adr1 ), + .ch18_am0( ch18_am0 ), + .ch18_am1( ch18_am1 ), + .pointer19( pointer19 ), + .pointer19_s( pointer19_s ), + .ch19_csr( ch19_csr ), + .ch19_txsz( ch19_txsz ), + .ch19_adr0( ch19_adr0 ), + .ch19_adr1( ch19_adr1 ), + .ch19_am0( ch19_am0 ), + .ch19_am1( ch19_am1 ), + .pointer20( pointer20 ), + .pointer20_s( pointer20_s ), + .ch20_csr( ch20_csr ), + .ch20_txsz( ch20_txsz ), + .ch20_adr0( ch20_adr0 ), + .ch20_adr1( ch20_adr1 ), + .ch20_am0( ch20_am0 ), + .ch20_am1( ch20_am1 ), + .pointer21( pointer21 ), + .pointer21_s( pointer21_s ), + .ch21_csr( ch21_csr ), + .ch21_txsz( ch21_txsz ), + .ch21_adr0( ch21_adr0 ), + .ch21_adr1( ch21_adr1 ), + .ch21_am0( ch21_am0 ), + .ch21_am1( ch21_am1 ), + .pointer22( pointer22 ), + .pointer22_s( pointer22_s ), + .ch22_csr( ch22_csr ), + .ch22_txsz( ch22_txsz ), + .ch22_adr0( ch22_adr0 ), + .ch22_adr1( ch22_adr1 ), + .ch22_am0( ch22_am0 ), + .ch22_am1( ch22_am1 ), + .pointer23( pointer23 ), + .pointer23_s( pointer23_s ), + .ch23_csr( ch23_csr ), + .ch23_txsz( ch23_txsz ), + .ch23_adr0( ch23_adr0 ), + .ch23_adr1( ch23_adr1 ), + .ch23_am0( ch23_am0 ), + .ch23_am1( ch23_am1 ), + .pointer24( pointer24 ), + .pointer24_s( pointer24_s ), + .ch24_csr( ch24_csr ), + .ch24_txsz( ch24_txsz ), + .ch24_adr0( ch24_adr0 ), + .ch24_adr1( ch24_adr1 ), + .ch24_am0( ch24_am0 ), + .ch24_am1( ch24_am1 ), + .pointer25( pointer25 ), + .pointer25_s( pointer25_s ), + .ch25_csr( ch25_csr ), + .ch25_txsz( ch25_txsz ), + .ch25_adr0( ch25_adr0 ), + .ch25_adr1( ch25_adr1 ), + .ch25_am0( ch25_am0 ), + .ch25_am1( ch25_am1 ), + .pointer26( pointer26 ), + .pointer26_s( pointer26_s ), + .ch26_csr( ch26_csr ), + .ch26_txsz( ch26_txsz ), + .ch26_adr0( ch26_adr0 ), + .ch26_adr1( ch26_adr1 ), + .ch26_am0( ch26_am0 ), + .ch26_am1( ch26_am1 ), + .pointer27( pointer27 ), + .pointer27_s( pointer27_s ), + .ch27_csr( ch27_csr ), + .ch27_txsz( ch27_txsz ), + .ch27_adr0( ch27_adr0 ), + .ch27_adr1( ch27_adr1 ), + .ch27_am0( ch27_am0 ), + .ch27_am1( ch27_am1 ), + .pointer28( pointer28 ), + .pointer28_s( pointer28_s ), + .ch28_csr( ch28_csr ), + .ch28_txsz( ch28_txsz ), + .ch28_adr0( ch28_adr0 ), + .ch28_adr1( ch28_adr1 ), + .ch28_am0( ch28_am0 ), + .ch28_am1( ch28_am1 ), + .pointer29( pointer29 ), + .pointer29_s( pointer29_s ), + .ch29_csr( ch29_csr ), + .ch29_txsz( ch29_txsz ), + .ch29_adr0( ch29_adr0 ), + .ch29_adr1( ch29_adr1 ), + .ch29_am0( ch29_am0 ), + .ch29_am1( ch29_am1 ), + .pointer30( pointer30 ), + .pointer30_s( pointer30_s ), + .ch30_csr( ch30_csr ), + .ch30_txsz( ch30_txsz ), + .ch30_adr0( ch30_adr0 ), + .ch30_adr1( ch30_adr1 ), + .ch30_am0( ch30_am0 ), + .ch30_am1( ch30_am1 ), + + .ch_sel( ch_sel ), + .ndnr( ndnr ), + .de_start( de_start ), + .ndr( ndr ), + .csr( csr ), + .pointer( pointer ), + .txsz( txsz ), + .adr0( adr0 ), + .adr1( adr1 ), + .am0( am0 ), + .am1( am1 ), + .pointer_s( pointer_s ), + .next_ch( next_ch ), + .de_ack( de_ack ), + .dma_busy( dma_busy ) + ); + + +// DMA Engine +wb_dma_de u2( + .clk( clk_i ), + .rst( ~rst_i ), + .mast0_go( mast0_go ), + .mast0_we( mast0_we ), + .mast0_adr( mast0_adr ), + .mast0_din( mast0_dout ), + .mast0_dout( mast0_din ), + .mast0_err( mast0_err ), + .mast0_drdy( mast0_drdy ), + .mast0_wait( mast0_wait ), + .mast1_go( mast1_go ), + .mast1_we( mast1_we ), + .mast1_adr( mast1_adr ), + .mast1_din( mast1_dout ), + .mast1_dout( mast1_din ), + .mast1_err( mast1_err ), + .mast1_drdy( mast1_drdy ), + .mast1_wait( mast1_wait ), + .de_start( de_start ), + .nd( ndr ), + .csr( csr ), + .pointer( pointer ), + .pointer_s( pointer_s ), + .txsz( txsz ), + .adr0( adr0 ), + .adr1( adr1 ), + .am0( am0 ), + .am1( am1 ), + .de_csr_we( de_csr_we ), + .de_txsz_we( de_txsz_we ), + .de_adr0_we( de_adr0_we ), + .de_adr1_we( de_adr1_we ), + .de_fetch_descr(de_fetch_descr ), + .ptr_set( ptr_set ), + .de_csr( de_csr ), + .de_txsz( de_txsz ), + .de_adr0( de_adr0 ), + .de_adr1( de_adr1 ), + .next_ch( next_ch ), + .de_ack( de_ack ), + .pause_req( pause_req ), + .paused( paused ), + .dma_abort( dma_abort ), + .dma_busy( dma_busy ), + .dma_err( dma_err ), + .dma_done( dma_done ), + .dma_done_all( dma_done_all ) + ); + +// Wishbone Interface 0 +wb_dma_wb_if #(rf_addr) u3( + .clk( clk_i ), + .rst( ~rst_i ), + .wbs_data_i( wb0s_data_i ), + .wbs_data_o( wb0s_data_o ), + .wb_addr_i( wb0_addr_i ), + .wb_sel_i( wb0_sel_i ), + .wb_we_i( wb0_we_i ), + .wb_cyc_i( wb0_cyc_i ), + .wb_stb_i( wb0_stb_i ), + .wb_ack_o( wb0_ack_o ), + .wb_err_o( wb0_err_o ), + .wb_rty_o( wb0_rty_o ), + .wbm_data_i( wb0m_data_i ), + .wbm_data_o( wb0m_data_o ), + .wb_addr_o( wb0_addr_o ), + .wb_sel_o( wb0_sel_o ), + .wb_we_o( wb0_we_o ), + .wb_cyc_o( wb0_cyc_o ), + .wb_stb_o( wb0_stb_o ), + .wb_ack_i( wb0_ack_i ), + .wb_err_i( wb0_err_i ), + .wb_rty_i( wb0_rty_i ), + .mast_go( mast0_go ), + .mast_we( mast0_we ), + .mast_adr( mast0_adr ), + .mast_din( mast0_din ), + .mast_dout( mast0_dout ), + .mast_err( mast0_err ), + .mast_drdy( mast0_drdy ), + .mast_wait( mast0_wait ), + .pt_sel_i( pt0_sel_i ), + .mast_pt_in( mast0_pt_in ), + .mast_pt_out( mast0_pt_out ), + .slv_adr( slv0_adr ), + .slv_din( slv0_din ), + .slv_dout( slv0_dout ), + .slv_re( slv0_re ), + .slv_we( slv0_we ), + .pt_sel_o( pt0_sel_o ), + .slv_pt_out( slv0_pt_out ), + .slv_pt_in( slv0_pt_in ) + ); + +// Wishbone Interface 1 +wb_dma_wb_if #(rf_addr) u4( + .clk( clk_i ), + .rst( ~rst_i ), + .wbs_data_i( wb1s_data_i ), + .wbs_data_o( wb1s_data_o ), + .wb_addr_i( wb1_addr_i ), + .wb_sel_i( wb1_sel_i ), + .wb_we_i( wb1_we_i ), + .wb_cyc_i( wb1_cyc_i ), + .wb_stb_i( wb1_stb_i ), + .wb_ack_o( wb1_ack_o ), + .wb_err_o( wb1_err_o ), + .wb_rty_o( wb1_rty_o ), + .wbm_data_i( wb1m_data_i ), + .wbm_data_o( wb1m_data_o ), + .wb_addr_o( wb1_addr_o ), + .wb_sel_o( wb1_sel_o ), + .wb_we_o( wb1_we_o ), + .wb_cyc_o( wb1_cyc_o ), + .wb_stb_o( wb1_stb_o ), + .wb_ack_i( wb1_ack_i ), + .wb_err_i( wb1_err_i ), + .wb_rty_i( wb1_rty_i ), + .mast_go( mast1_go ), + .mast_we( mast1_we ), + .mast_adr( mast1_adr ), + .mast_din( mast1_din ), + .mast_dout( mast1_dout ), + .mast_err( mast1_err ), + .mast_drdy( mast1_drdy ), + .mast_wait( mast1_wait ), + .pt_sel_i( pt1_sel_i ), + .mast_pt_in( mast1_pt_in ), + .mast_pt_out( mast1_pt_out ), + .slv_adr( slv1_adr ), + .slv_din( 32'h0 ), // Not Connected + .slv_dout( slv1_dout ), // Not Connected + .slv_re( slv1_re ), // Not Connected + .slv_we( slv1_we ), // Not Connected + .pt_sel_o( pt1_sel_o ), + .slv_pt_out( slv1_pt_out ), + .slv_pt_in( slv1_pt_in ) + ); + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v new file mode 100644 index 000000000..4bc905d23 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v @@ -0,0 +1,223 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA WISHBONE Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_wb_if.v,v 1.3 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_wb_if.v,v $ +// Revision 1.3 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.2 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:54 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_wb_if(clk, rst, + + // Wishbone + wbs_data_i, wbs_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, wb_rty_o, + wbm_data_i, wbm_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o, + wb_stb_o, wb_ack_i, wb_err_i, wb_rty_i, + + // Master + mast_go, mast_we, mast_adr, mast_din, mast_dout, mast_err, + mast_drdy, mast_wait, pt_sel_i, mast_pt_in, mast_pt_out, + + // Slave + slv_adr, slv_din, slv_dout, slv_re, slv_we, + pt_sel_o, slv_pt_out, slv_pt_in + + ); + +parameter rf_addr = 0; + +input clk, rst; + +// -------------------------------------- +// WISHBONE INTERFACE + +// Slave Interface +input [31:0] wbs_data_i; +output [31:0] wbs_data_o; +input [31:0] wb_addr_i; +input [3:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; +output wb_rty_o; + +// Master Interface +input [31:0] wbm_data_i; +output [31:0] wbm_data_o; +output [31:0] wb_addr_o; +output [3:0] wb_sel_o; +output wb_we_o; +output wb_cyc_o; +output wb_stb_o; +input wb_ack_i; +input wb_err_i; +input wb_rty_i; + +// -------------------------------------- +// MASTER INTERFACE +input mast_go; // Perform a Master Cycle (as long as this + // line is asserted) +input mast_we; // Read/Write +input [31:0] mast_adr; // Address for the transfer +input [31:0] mast_din; // Internal Input Data +output [31:0] mast_dout; // Internal Output Data +output mast_err; // Indicates an error has occurred + +output mast_drdy; // Indicated that either data is available + // during a read, or that the master can accept + // the next data during a write +input mast_wait; // Tells the master to insert wait cycles + // because data can not be accepted/provided + +// Pass Through Interface +input pt_sel_i; // Pass Through Mode Selected +input [70:0] mast_pt_in; // Grouped WISHBONE inputs +output [34:0] mast_pt_out; // Grouped WISHBONE outputs + +// -------------------------------------- +// Slave INTERFACE + +// This is the register File Interface +output [31:0] slv_adr; // Slave Address +input [31:0] slv_din; // Slave Input Data +output [31:0] slv_dout; // Slave Output Data +output slv_re; // Slave Read Enable +output slv_we; // Slave Write Enable + +// Pass through Interface +output pt_sel_o; // Pass Through Mode Active +output [70:0] slv_pt_out; // Grouped WISHBONE out signals +input [34:0] slv_pt_in; // Grouped WISHBONE in signals + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +wb_dma_wb_mast u0( + .clk( clk ), + .rst( rst ), + .wb_data_i( wbs_data_i ), + .wb_data_o( wbs_data_o ), + .wb_addr_o( wb_addr_o ), + .wb_sel_o( wb_sel_o ), + .wb_we_o( wb_we_o ), + .wb_cyc_o( wb_cyc_o ), + .wb_stb_o( wb_stb_o ), + .wb_ack_i( wb_ack_i ), + .wb_err_i( wb_err_i ), + .wb_rty_i( wb_rty_i ), + .mast_go( mast_go ), + .mast_we( mast_we ), + .mast_adr( mast_adr ), + .mast_din( mast_din ), + .mast_dout( mast_dout ), + .mast_err( mast_err ), + .mast_drdy( mast_drdy ), + .mast_wait( mast_wait ), + .pt_sel( pt_sel_i ), + .mast_pt_in( mast_pt_in ), + .mast_pt_out( mast_pt_out ) + ); + + +wb_dma_wb_slv #(rf_addr) u1( + .clk( clk ), + .rst( rst ), + .wb_data_i( wbm_data_i ), + .wb_data_o( wbm_data_o ), + .wb_addr_i( wb_addr_i ), + .wb_sel_i( wb_sel_i ), + .wb_we_i( wb_we_i ), + .wb_cyc_i( wb_cyc_i ), + .wb_stb_i( wb_stb_i ), + .wb_ack_o( wb_ack_o ), + .wb_err_o( wb_err_o ), + .wb_rty_o( wb_rty_o ), + .slv_adr( slv_adr ), + .slv_din( slv_din ), + .slv_dout( slv_dout ), + .slv_re( slv_re ), + .slv_we( slv_we ), + .pt_sel( pt_sel_o ), + .slv_pt_out( slv_pt_out ), + .slv_pt_in( slv_pt_in ) + ); + + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v new file mode 100644 index 000000000..fce62d23b --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v @@ -0,0 +1,170 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA WISHBONE Master Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_wb_mast.v,v 1.2 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_wb_mast.v,v $ +// Revision 1.2 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:11:05 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_wb_mast(clk, rst, + + wb_data_i, wb_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o, + wb_stb_o, wb_ack_i, wb_err_i, wb_rty_i, + + mast_go, mast_we, mast_adr, mast_din, mast_dout, mast_err, + mast_drdy, mast_wait, + + pt_sel, mast_pt_in, mast_pt_out + ); + +input clk, rst; + +// -------------------------------------- +// WISHBONE INTERFACE + +input [31:0] wb_data_i; +output [31:0] wb_data_o; +output [31:0] wb_addr_o; +output [3:0] wb_sel_o; +output wb_we_o; +output wb_cyc_o; +output wb_stb_o; +input wb_ack_i; +input wb_err_i; +input wb_rty_i; + +// -------------------------------------- +// INTERNAL DMA INTERFACE +input mast_go; // Perform a Master Cycle (as long as this + // line is asserted) +input mast_we; // Read/Write +input [31:0] mast_adr; // Address for the transfer +input [31:0] mast_din; // Internal Input Data +output [31:0] mast_dout; // Internal Output Data +output mast_err; // Indicates an error has occurred + +output mast_drdy; // Indicated that either data is available + // during a read, or that the master can accept + // the next data during a write +input mast_wait; // Tells the master to insert wait cycles + // because data can not be accepted/provided + +// Pass Through Interface +input pt_sel; // Pass Through Mode Selected +input [70:0] mast_pt_in; // Grouped WISHBONE inputs +output [34:0] mast_pt_out; // Grouped WISHBONE outputs + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg mast_cyc, mast_stb; +reg mast_we_r; +reg [3:0] mast_be; +reg [31:0] mast_dout; + +//////////////////////////////////////////////////////////////////// +// +// Pass-Through Interface +// + +assign {wb_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o, wb_stb_o} = + pt_sel ? mast_pt_in : + {mast_din, mast_adr, mast_be, mast_we_r, mast_cyc, mast_stb}; + +assign mast_pt_out = {wb_data_i, wb_ack_i, wb_err_i, wb_rty_i}; + +//////////////////////////////////////////////////////////////////// +// +// DMA Engine Interface +// + +always @(posedge clk) + if(wb_ack_i) mast_dout <= #1 wb_data_i; + +always @(posedge clk) + mast_be <= #1 4'hf; + +always @(posedge clk) + mast_we_r <= #1 mast_we; + +always @(posedge clk) + mast_cyc <= #1 mast_go; + +always @(posedge clk) + mast_stb <= #1 mast_go & !mast_wait; + +assign mast_drdy = wb_ack_i; +assign mast_err = wb_err_i; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v new file mode 100644 index 000000000..b3f76e444 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v @@ -0,0 +1,180 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE DMA WISHBONE Slave Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/wb_dma/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: wb_dma_wb_slv.v,v 1.4 2002/02/01 01:54:45 rudi Exp $ +// +// $Date: 2002/02/01 01:54:45 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: wb_dma_wb_slv.v,v $ +// Revision 1.4 2002/02/01 01:54:45 rudi +// +// - Minor cleanup +// +// Revision 1.3 2001/10/19 04:35:04 rudi +// +// - Made the core parameterized +// +// Revision 1.2 2001/08/15 05:40:30 rudi +// +// - Changed IO names to be more clear. +// - Uniquifyed define names to be core specific. +// - Added Section 3.10, describing DMA restart. +// +// Revision 1.1 2001/07/29 08:57:02 rudi +// +// +// 1) Changed Directory Structure +// 2) Added restart signal (REST) +// +// Revision 1.2 2001/06/05 10:22:37 rudi +// +// +// - Added Support of up to 31 channels +// - Added support for 2,4 and 8 priority levels +// - Now can have up to 31 channels +// - Added many configuration items +// - Changed reset to async +// +// Revision 1.1.1.1 2001/03/19 13:10:59 rudi +// Initial Release +// +// +// + +`include "wb_dma_defines.v" + +module wb_dma_wb_slv(clk, rst, + + wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, + wb_stb_i, wb_ack_o, wb_err_o, wb_rty_o, + + // This is the register File Interface + slv_adr, slv_din, slv_dout, slv_re, slv_we, + + // Pass through Interface + pt_sel, slv_pt_out, slv_pt_in + + ); + +parameter rf_addr = 0; + +input clk, rst; + +// -------------------------------------- +// WISHBONE INTERFACE + +input [31:0] wb_data_i; +output [31:0] wb_data_o; +input [31:0] wb_addr_i; +input [3:0] wb_sel_i; +input wb_we_i; +input wb_cyc_i; +input wb_stb_i; +output wb_ack_o; +output wb_err_o; +output wb_rty_o; + +// This is the register File Interface +output [31:0] slv_adr; // Slave Address +input [31:0] slv_din; // Slave Input Data +output [31:0] slv_dout; // Slave Output Data +output slv_re; // Slave Read Enable +output slv_we; // Slave Write Enable + +// Pass through Interface +output pt_sel; // Pass Through Mode Active +output [70:0] slv_pt_out; // Grouped WISHBONE out signals +input [34:0] slv_pt_in; // Grouped WISHBONE in signals + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg slv_re, slv_we; +wire rf_sel; +reg rf_ack; +reg [31:0] slv_adr, slv_dout; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign rf_sel = `WDMA_REG_SEL ; + +//////////////////////////////////////////////////////////////////// +// +// Pass Through Logic +// + +//assign pt_sel = !rf_sel; +assign pt_sel = !rf_sel & wb_cyc_i; + +assign slv_pt_out = {wb_data_i, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i}; +assign {wb_data_o, wb_ack_o, wb_err_o, wb_rty_o} = pt_sel ? slv_pt_in : + {slv_din, rf_ack, 1'b0, 1'b0}; + +//////////////////////////////////////////////////////////////////// +// +// Register File Logic +// + +always @(posedge clk) + slv_adr <= #1 wb_addr_i; + +always @(posedge clk) + slv_re <= #1 rf_sel & wb_cyc_i & wb_stb_i & !wb_we_i & !rf_ack & !slv_re; + +always @(posedge clk) + slv_we <= #1 rf_sel & wb_cyc_i & wb_stb_i & wb_we_i & !rf_ack; + +always @(posedge clk) + slv_dout <= #1 wb_data_i; + +always @(posedge clk) + rf_ack <= #1 (slv_re | slv_we) & wb_cyc_i & wb_stb_i & !rf_ack ; + +endmodule From 26d3b5a9546ec8a951f277f26705578cb20b48ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:08:58 -0600 Subject: [PATCH 123/352] [Benchmark] Reorganize iwls2005 benchmark: separate the location of rtl and testbenches --- .../iwls2005/ac97_ctrl/{ => rtl}/ac97_cra.v | 0 .../ac97_ctrl/{ => rtl}/ac97_defines.v | 0 .../ac97_ctrl/{ => rtl}/ac97_dma_if.v | 0 .../ac97_ctrl/{ => rtl}/ac97_dma_req.v | 0 .../ac97_ctrl/{ => rtl}/ac97_fifo_ctrl.v | 0 .../ac97_ctrl/{ => rtl}/ac97_in_fifo.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_int.v | 0 .../ac97_ctrl/{ => rtl}/ac97_out_fifo.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_prc.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_rf.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_rst.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_sin.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_soc.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_sout.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_top.v | 0 .../iwls2005/ac97_ctrl/{ => rtl}/ac97_wb_if.v | 0 .../aes_core/{ => rtl}/aes_cipher_top.v | 0 .../aes_core/{ => rtl}/aes_inv_cipher_top.v | 0 .../aes_core/{ => rtl}/aes_inv_sbox.v | 0 .../aes_core/{ => rtl}/aes_key_expand_128.v | 0 .../iwls2005/aes_core/{ => rtl}/aes_rcon.v | 0 .../iwls2005/aes_core/{ => rtl}/aes_sbox.v | 0 .../iwls2005/aes_core/{ => rtl}/timescale.v | 0 .../des/{common => area_opt/rtl}/crp.v | 0 .../iwls2005/des/area_opt/{ => rtl}/des.v | 0 .../iwls2005/des/area_opt/{ => rtl}/des3.v | 0 .../iwls2005/des/area_opt/{ => rtl}/key_sel.v | 0 .../des/area_opt/{ => rtl}/key_sel3.v | 0 .../des/{common => area_opt/rtl}/sbox1.v | 0 .../des/{common => area_opt/rtl}/sbox2.v | 0 .../des/{common => area_opt/rtl}/sbox3.v | 0 .../des/{common => area_opt/rtl}/sbox4.v | 0 .../des/{common => area_opt/rtl}/sbox5.v | 0 .../des/{common => area_opt/rtl}/sbox6.v | 0 .../des/{common => area_opt/rtl}/sbox7.v | 0 .../des/{common => area_opt/rtl}/sbox8.v | 0 .../iwls2005/des/perf_opt/{ => rtl}/des.v | 0 .../iwls2005/des/perf_opt/{ => rtl}/des3.v | 0 .../iwls2005/des/perf_opt/{ => rtl}/key_sel.v | 0 .../iwls2005/des/perf_opt/rtl/sbox1.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox2.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox3.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox4.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox5.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox6.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox7.v | 113 ++++++++++++++++++ .../iwls2005/des/perf_opt/rtl/sbox8.v | 113 ++++++++++++++++++ .../ethernet/{ => rtl}/eth_clockgen.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_crc.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_defines.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_fifo.v | 0 .../ethernet/{ => rtl}/eth_maccontrol.v | 0 .../ethernet/{ => rtl}/eth_macstatus.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_miim.v | 0 .../ethernet/{ => rtl}/eth_outputcontrol.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_random.v | 0 .../ethernet/{ => rtl}/eth_receivecontrol.v | 0 .../ethernet/{ => rtl}/eth_register.v | 0 .../ethernet/{ => rtl}/eth_registers.v | 0 .../ethernet/{ => rtl}/eth_rxaddrcheck.v | 0 .../ethernet/{ => rtl}/eth_rxcounters.v | 0 .../ethernet/{ => rtl}/eth_rxethmac.v | 0 .../ethernet/{ => rtl}/eth_rxstatem.v | 0 .../ethernet/{ => rtl}/eth_shiftreg.v | 0 .../ethernet/{ => rtl}/eth_spram_256x32.v | 0 .../iwls2005/ethernet/{ => rtl}/eth_top.v | 0 .../ethernet/{ => rtl}/eth_transmitcontrol.v | 0 .../ethernet/{ => rtl}/eth_txcounters.v | 0 .../ethernet/{ => rtl}/eth_txethmac.v | 0 .../ethernet/{ => rtl}/eth_txstatem.v | 0 .../ethernet/{ => rtl}/eth_wishbone.v | 0 .../iwls2005/ethernet/{ => rtl}/timescale.v | 0 .../{ => rtl}/xilinx_dist_ram_16x32.v | 0 .../ethernet/{ => testbench}/eth_cop.v | 0 .../iwls2005/fpu/{ => rtl}/except.v | 0 .../benchmarks/iwls2005/fpu/{ => rtl}/fpu.v | 0 .../iwls2005/fpu/{ => rtl}/post_norm.v | 0 .../iwls2005/fpu/{ => rtl}/pre_norm.v | 0 .../iwls2005/fpu/{ => rtl}/pre_norm_fmul.v | 0 .../iwls2005/fpu/{ => rtl}/primitives.v | 0 .../i2c/{ => rtl}/i2c_master_bit_ctrl.v | 0 .../i2c/{ => rtl}/i2c_master_byte_ctrl.v | 0 .../i2c/{ => rtl}/i2c_master_defines.v | 0 .../iwls2005/i2c/{ => rtl}/i2c_master_top.v | 0 .../iwls2005/i2c/{ => rtl}/timescale.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_adr_sel.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_cs_rf.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_defines.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_dp.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_incn_r.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_mem_if.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_obct.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_obct_top.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_rd_fifo.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_refresh.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_rf.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_timing.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_top.v | 0 .../iwls2005/mem_ctrl/{ => rtl}/mc_wb_if.v | 0 .../iwls2005/pci/{ => rtl}/bus_commands.v | 0 .../pci/{ => rtl}/pci_async_reset_flop.v | 0 .../iwls2005/pci/{ => rtl}/pci_bridge32.v | 0 .../iwls2005/pci/{ => rtl}/pci_cbe_en_crit.v | 0 .../pci/{ => rtl}/pci_conf_cyc_addr_dec.v | 0 .../iwls2005/pci/{ => rtl}/pci_conf_space.v | 0 .../iwls2005/pci/{ => rtl}/pci_constants.v | 0 .../iwls2005/pci/{ => rtl}/pci_cur_out_reg.v | 0 .../iwls2005/pci/{ => rtl}/pci_delayed_sync.v | 0 .../pci/{ => rtl}/pci_delayed_write_reg.v | 0 .../iwls2005/pci/{ => rtl}/pci_frame_crit.v | 0 .../pci/{ => rtl}/pci_frame_en_crit.v | 0 .../pci/{ => rtl}/pci_frame_load_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_in_reg.v | 0 .../iwls2005/pci/{ => rtl}/pci_io_mux.v | 0 .../pci/{ => rtl}/pci_io_mux_ad_en_crit.v | 0 .../pci/{ => rtl}/pci_io_mux_ad_load_crit.v | 0 .../pci/{ => rtl}/pci_irdy_out_crit.v | 0 .../pci/{ => rtl}/pci_mas_ad_en_crit.v | 0 .../pci/{ => rtl}/pci_mas_ad_load_crit.v | 0 .../pci/{ => rtl}/pci_mas_ch_state_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_master32_sm.v | 0 .../pci/{ => rtl}/pci_master32_sm_if.v | 0 .../iwls2005/pci/{ => rtl}/pci_out_reg.v | 0 .../iwls2005/pci/{ => rtl}/pci_par_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_parity_check.v | 0 .../iwls2005/pci/{ => rtl}/pci_pci_decoder.v | 0 .../iwls2005/pci/{ => rtl}/pci_pci_tpram.v | 0 .../pci/{ => rtl}/pci_pcir_fifo_control.v | 0 .../pci/{ => rtl}/pci_pciw_fifo_control.v | 0 .../pci/{ => rtl}/pci_pciw_pcir_fifos.v | 0 .../iwls2005/pci/{ => rtl}/pci_perr_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_perr_en_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_ram_16x40d.v | 0 .../iwls2005/pci/{ => rtl}/pci_rst_int.v | 0 .../iwls2005/pci/{ => rtl}/pci_serr_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_serr_en_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_spoci_ctrl.v | 0 .../iwls2005/pci/{ => rtl}/pci_sync_module.v | 0 .../pci/{ => rtl}/pci_synchronizer_flop.v | 0 .../pci/{ => rtl}/pci_target32_clk_en.v | 0 .../pci/{ => rtl}/pci_target32_devs_crit.v | 0 .../pci/{ => rtl}/pci_target32_interface.v | 0 .../iwls2005/pci/{ => rtl}/pci_target32_sm.v | 0 .../pci/{ => rtl}/pci_target32_stop_crit.v | 0 .../pci/{ => rtl}/pci_target32_trdy_crit.v | 0 .../iwls2005/pci/{ => rtl}/pci_target_unit.v | 0 .../pci/{ => rtl}/pci_user_constants.v | 0 .../iwls2005/pci/{ => rtl}/pci_wb_addr_mux.v | 0 .../iwls2005/pci/{ => rtl}/pci_wb_decoder.v | 0 .../iwls2005/pci/{ => rtl}/pci_wb_master.v | 0 .../iwls2005/pci/{ => rtl}/pci_wb_slave.v | 0 .../pci/{ => rtl}/pci_wb_slave_unit.v | 0 .../iwls2005/pci/{ => rtl}/pci_wb_tpram.v | 0 .../pci/{ => rtl}/pci_wbr_fifo_control.v | 0 .../pci/{ => rtl}/pci_wbs_wbb3_2_wbb2.v | 0 .../pci/{ => rtl}/pci_wbw_fifo_control.v | 0 .../pci/{ => rtl}/pci_wbw_wbr_fifos.v | 0 .../iwls2005/pci/{ => rtl}/timescale.v | 0 .../iwls2005/sasc/{ => rtl}/sasc_brg.v | 0 .../iwls2005/sasc/{ => rtl}/sasc_fifo4.v | 0 .../iwls2005/sasc/{ => rtl}/sasc_top.v | 0 .../iwls2005/sasc/{ => rtl}/timescale.v | 0 .../iwls2005/simple_spi/{ => rtl}/fifo4.v | 0 .../simple_spi/{ => rtl}/simple_spi_top.v | 0 .../iwls2005/spi/{ => rtl}/spi_clgen.v | 0 .../iwls2005/spi/{ => rtl}/spi_defines.v | 0 .../iwls2005/spi/{ => rtl}/spi_shift.v | 0 .../iwls2005/spi/{ => rtl}/spi_top.v | 0 .../iwls2005/spi/{ => rtl}/timescale.v | 0 .../iwls2005/ss_pcm/{ => rtl}/pcm_slv_top.v | 0 .../iwls2005/ss_pcm/{ => rtl}/timescale.v | 0 .../{ => rtl}/StepperMotorDrive.vhd | 0 .../iwls2005/systemcaes/{ => rtl}/aes.v | 0 .../systemcaes/{ => rtl}/byte_mixcolum.v | 0 .../iwls2005/systemcaes/{ => rtl}/keysched.v | 0 .../iwls2005/systemcaes/{ => rtl}/mixcolum.v | 0 .../iwls2005/systemcaes/{ => rtl}/sbox.v | 0 .../iwls2005/systemcaes/{ => rtl}/subbytes.v | 0 .../iwls2005/systemcaes/{ => rtl}/timescale.v | 0 .../systemcaes/{ => rtl}/word_mixcolum.v | 0 .../iwls2005/systemcdes/{ => rtl}/des.v | 0 .../iwls2005/systemcdes/{ => rtl}/desround.v | 0 .../iwls2005/systemcdes/{ => rtl}/key_gen.v | 0 .../iwls2005/systemcdes/{ => rtl}/s1.v | 0 .../iwls2005/systemcdes/{ => rtl}/s2.v | 0 .../iwls2005/systemcdes/{ => rtl}/s3.v | 0 .../iwls2005/systemcdes/{ => rtl}/s4.v | 0 .../iwls2005/systemcdes/{ => rtl}/s5.v | 0 .../iwls2005/systemcdes/{ => rtl}/s6.v | 0 .../iwls2005/systemcdes/{ => rtl}/s7.v | 0 .../iwls2005/systemcdes/{ => rtl}/s8.v | 0 .../iwls2005/tv80/{ => rtl}/tv80_alu.v | 0 .../iwls2005/tv80/{ => rtl}/tv80_core.v | 0 .../iwls2005/tv80/{ => rtl}/tv80_mcode.v | 0 .../iwls2005/tv80/{ => rtl}/tv80_reg.v | 0 .../iwls2005/tv80/{ => rtl}/tv80s.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_crc16.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_crc5.v | 0 .../usb_funct/{ => rtl}/usbf_defines.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_ep_rf.v | 0 .../usb_funct/{ => rtl}/usbf_ep_rf_dummy.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_idma.v | 0 .../usb_funct/{ => rtl}/usbf_mem_arb.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_pa.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_pd.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_pe.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_pl.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_rf.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_top.v | 0 .../usb_funct/{ => rtl}/usbf_utmi_if.v | 0 .../usb_funct/{ => rtl}/usbf_utmi_ls.v | 0 .../iwls2005/usb_funct/{ => rtl}/usbf_wb.v | 0 .../iwls2005/usb_phy/{ => rtl}/timescale.v | 0 .../iwls2005/usb_phy/{ => rtl}/usb_phy.v | 0 .../iwls2005/usb_phy/{ => rtl}/usb_rx_phy.v | 0 .../iwls2005/usb_phy/{ => rtl}/usb_tx_phy.v | 0 .../vga_lcd/{ => rtl}/generic_dpram.v | 0 .../vga_lcd/{ => rtl}/generic_spram.v | 0 .../iwls2005/vga_lcd/{ => rtl}/timescale.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_clkgen.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_colproc.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_csm_pb.v | 0 .../vga_lcd/{ => rtl}/vga_cur_cregs.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_curproc.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_defines.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_enh_top.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_fifo.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_fifo_dc.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_pgen.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_tgen.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_vtim.v | 0 .../vga_lcd/{ => rtl}/vga_wb_master.v | 0 .../iwls2005/vga_lcd/{ => rtl}/vga_wb_slave.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_arb.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_defines.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_master_if.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_msel.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_pri_dec.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_pri_enc.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_rf.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_slave_if.v | 0 .../wb_conmax/{ => rtl}/wb_conmax_top.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_ch_arb.v | 0 .../wb_dma/{ => rtl}/wb_dma_ch_pri_enc.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_ch_rf.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_ch_sel.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_de.v | 0 .../wb_dma/{ => rtl}/wb_dma_defines.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_inc30r.v | 0 .../wb_dma/{ => rtl}/wb_dma_pri_enc_sub.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_rf.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_top.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_wb_if.v | 0 .../wb_dma/{ => rtl}/wb_dma_wb_mast.v | 0 .../iwls2005/wb_dma/{ => rtl}/wb_dma_wb_slv.v | 0 255 files changed, 904 insertions(+) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_cra.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_dma_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_dma_req.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_fifo_ctrl.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_in_fifo.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_int.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_out_fifo.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_prc.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_rst.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_sin.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_soc.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_sout.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/ac97_ctrl/{ => rtl}/ac97_wb_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_cipher_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_inv_cipher_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_inv_sbox.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_key_expand_128.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_rcon.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/aes_sbox.v (100%) rename openfpga_flow/benchmarks/iwls2005/aes_core/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/crp.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/area_opt/{ => rtl}/des.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/area_opt/{ => rtl}/des3.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/area_opt/{ => rtl}/key_sel.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/area_opt/{ => rtl}/key_sel3.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox1.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox2.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox3.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox4.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox5.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox6.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox7.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/{common => area_opt/rtl}/sbox8.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/perf_opt/{ => rtl}/des.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/perf_opt/{ => rtl}/des3.v (100%) rename openfpga_flow/benchmarks/iwls2005/des/perf_opt/{ => rtl}/key_sel.v (100%) create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox1.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox2.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox3.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox4.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox5.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox6.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox7.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox8.v rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_clockgen.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_crc.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_fifo.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_maccontrol.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_macstatus.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_miim.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_outputcontrol.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_random.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_receivecontrol.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_register.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_registers.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_rxaddrcheck.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_rxcounters.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_rxethmac.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_rxstatem.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_shiftreg.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_spram_256x32.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_transmitcontrol.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_txcounters.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_txethmac.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_txstatem.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/eth_wishbone.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => rtl}/xilinx_dist_ram_16x32.v (100%) rename openfpga_flow/benchmarks/iwls2005/ethernet/{ => testbench}/eth_cop.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/except.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/fpu.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/post_norm.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/pre_norm.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/pre_norm_fmul.v (100%) rename openfpga_flow/benchmarks/iwls2005/fpu/{ => rtl}/primitives.v (100%) rename openfpga_flow/benchmarks/iwls2005/i2c/{ => rtl}/i2c_master_bit_ctrl.v (100%) rename openfpga_flow/benchmarks/iwls2005/i2c/{ => rtl}/i2c_master_byte_ctrl.v (100%) rename openfpga_flow/benchmarks/iwls2005/i2c/{ => rtl}/i2c_master_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/i2c/{ => rtl}/i2c_master_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/i2c/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_adr_sel.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_cs_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_dp.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_incn_r.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_mem_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_obct.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_obct_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_rd_fifo.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_refresh.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_timing.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/mem_ctrl/{ => rtl}/mc_wb_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/bus_commands.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_async_reset_flop.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_bridge32.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_cbe_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_conf_cyc_addr_dec.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_conf_space.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_constants.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_cur_out_reg.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_delayed_sync.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_delayed_write_reg.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_frame_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_frame_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_frame_load_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_in_reg.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_io_mux.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_io_mux_ad_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_io_mux_ad_load_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_irdy_out_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_mas_ad_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_mas_ad_load_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_mas_ch_state_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_master32_sm.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_master32_sm_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_out_reg.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_par_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_parity_check.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_pci_decoder.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_pci_tpram.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_pcir_fifo_control.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_pciw_fifo_control.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_pciw_pcir_fifos.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_perr_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_perr_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_ram_16x40d.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_rst_int.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_serr_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_serr_en_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_spoci_ctrl.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_sync_module.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_synchronizer_flop.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_clk_en.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_devs_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_interface.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_sm.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_stop_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target32_trdy_crit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_target_unit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_user_constants.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_addr_mux.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_decoder.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_master.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_slave.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_slave_unit.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wb_tpram.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wbr_fifo_control.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wbs_wbb3_2_wbb2.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wbw_fifo_control.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/pci_wbw_wbr_fifos.v (100%) rename openfpga_flow/benchmarks/iwls2005/pci/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/sasc/{ => rtl}/sasc_brg.v (100%) rename openfpga_flow/benchmarks/iwls2005/sasc/{ => rtl}/sasc_fifo4.v (100%) rename openfpga_flow/benchmarks/iwls2005/sasc/{ => rtl}/sasc_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/sasc/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/simple_spi/{ => rtl}/fifo4.v (100%) rename openfpga_flow/benchmarks/iwls2005/simple_spi/{ => rtl}/simple_spi_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/spi/{ => rtl}/spi_clgen.v (100%) rename openfpga_flow/benchmarks/iwls2005/spi/{ => rtl}/spi_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/spi/{ => rtl}/spi_shift.v (100%) rename openfpga_flow/benchmarks/iwls2005/spi/{ => rtl}/spi_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/spi/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/ss_pcm/{ => rtl}/pcm_slv_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/ss_pcm/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/steppermotordrive/{ => rtl}/StepperMotorDrive.vhd (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/aes.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/byte_mixcolum.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/keysched.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/mixcolum.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/sbox.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/subbytes.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcaes/{ => rtl}/word_mixcolum.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/des.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/desround.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/key_gen.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s1.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s2.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s3.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s4.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s5.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s6.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s7.v (100%) rename openfpga_flow/benchmarks/iwls2005/systemcdes/{ => rtl}/s8.v (100%) rename openfpga_flow/benchmarks/iwls2005/tv80/{ => rtl}/tv80_alu.v (100%) rename openfpga_flow/benchmarks/iwls2005/tv80/{ => rtl}/tv80_core.v (100%) rename openfpga_flow/benchmarks/iwls2005/tv80/{ => rtl}/tv80_mcode.v (100%) rename openfpga_flow/benchmarks/iwls2005/tv80/{ => rtl}/tv80_reg.v (100%) rename openfpga_flow/benchmarks/iwls2005/tv80/{ => rtl}/tv80s.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_crc16.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_crc5.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_ep_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_ep_rf_dummy.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_idma.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_mem_arb.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_pa.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_pd.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_pe.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_pl.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_utmi_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_utmi_ls.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_funct/{ => rtl}/usbf_wb.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_phy/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_phy/{ => rtl}/usb_phy.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_phy/{ => rtl}/usb_rx_phy.v (100%) rename openfpga_flow/benchmarks/iwls2005/usb_phy/{ => rtl}/usb_tx_phy.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/generic_dpram.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/generic_spram.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/timescale.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_clkgen.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_colproc.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_csm_pb.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_cur_cregs.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_curproc.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_enh_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_fifo.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_fifo_dc.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_pgen.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_tgen.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_vtim.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_wb_master.v (100%) rename openfpga_flow/benchmarks/iwls2005/vga_lcd/{ => rtl}/vga_wb_slave.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_arb.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_master_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_msel.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_pri_dec.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_pri_enc.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_slave_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_conmax/{ => rtl}/wb_conmax_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_ch_arb.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_ch_pri_enc.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_ch_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_ch_sel.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_de.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_defines.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_inc30r.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_pri_enc_sub.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_rf.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_top.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_wb_if.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_wb_mast.v (100%) rename openfpga_flow/benchmarks/iwls2005/wb_dma/{ => rtl}/wb_dma_wb_slv.v (100%) diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_cra.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_cra.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_cra.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_defines.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_dma_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_if.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_dma_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_dma_req.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_dma_req.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_dma_req.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_fifo_ctrl.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_fifo_ctrl.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_fifo_ctrl.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_in_fifo.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_in_fifo.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_in_fifo.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_int.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_int.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_int.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_out_fifo.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_out_fifo.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_out_fifo.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_prc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_prc.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_prc.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rf.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_rst.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_rst.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_rst.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_sin.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sin.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_sin.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_soc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_soc.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_soc.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_sout.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_sout.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_sout.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_top.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v b/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_wb_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ac97_ctrl/ac97_wb_if.v rename to openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/ac97_wb_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_cipher_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_cipher_top.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_cipher_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_inv_cipher_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_cipher_top.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_inv_cipher_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_inv_sbox.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_inv_sbox.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_inv_sbox.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_key_expand_128.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_key_expand_128.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_key_expand_128.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_rcon.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_rcon.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_rcon.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_sbox.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/aes_sbox.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/aes_sbox.v diff --git a/openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v b/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/aes_core/timescale.v rename to openfpga_flow/benchmarks/iwls2005/aes_core/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/crp.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/crp.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/crp.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/crp.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/des.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/area_opt/des.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/des.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/des3.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/area_opt/des3.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/des3.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/key_sel.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/key_sel.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/key_sel3.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/area_opt/key_sel3.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/key_sel3.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox1.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox1.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox1.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox2.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox2.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox2.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox3.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox3.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox3.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox4.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox4.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox4.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox5.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox5.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox5.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox6.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox6.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox6.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox7.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox7.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox7.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v b/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox8.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/common/sbox8.v rename to openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/sbox8.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/des.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/perf_opt/des.v rename to openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/des.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/des3.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/perf_opt/des3.v rename to openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/des3.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/des/perf_opt/key_sel.v rename to openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox1.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox1.v new file mode 100644 index 000000000..76d5e22f6 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox1.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox1(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 14; + 1: dout = 4; + 2: dout = 13; + 3: dout = 1; + 4: dout = 2; + 5: dout = 15; + 6: dout = 11; + 7: dout = 8; + 8: dout = 3; + 9: dout = 10; + 10: dout = 6; + 11: dout = 12; + 12: dout = 5; + 13: dout = 9; + 14: dout = 0; + 15: dout = 7; + + 16: dout = 0; + 17: dout = 15; + 18: dout = 7; + 19: dout = 4; + 20: dout = 14; + 21: dout = 2; + 22: dout = 13; + 23: dout = 1; + 24: dout = 10; + 25: dout = 6; + 26: dout = 12; + 27: dout = 11; + 28: dout = 9; + 29: dout = 5; + 30: dout = 3; + 31: dout = 8; + + 32: dout = 4; + 33: dout = 1; + 34: dout = 14; + 35: dout = 8; + 36: dout = 13; + 37: dout = 6; + 38: dout = 2; + 39: dout = 11; + 40: dout = 15; + 41: dout = 12; + 42: dout = 9; + 43: dout = 7; + 44: dout = 3; + 45: dout = 10; + 46: dout = 5; + 47: dout = 0; + + 48: dout = 15; + 49: dout = 12; + 50: dout = 8; + 51: dout = 2; + 52: dout = 4; + 53: dout = 9; + 54: dout = 1; + 55: dout = 7; + 56: dout = 5; + 57: dout = 11; + 58: dout = 3; + 59: dout = 14; + 60: dout = 10; + 61: dout = 0; + 62: dout = 6; + 63: dout = 13; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox2.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox2.v new file mode 100644 index 000000000..aa505f3a2 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox2.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox2(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 15; + 1: dout = 1; + 2: dout = 8; + 3: dout = 14; + 4: dout = 6; + 5: dout = 11; + 6: dout = 3; + 7: dout = 4; + 8: dout = 9; + 9: dout = 7; + 10: dout = 2; + 11: dout = 13; + 12: dout = 12; + 13: dout = 0; + 14: dout = 5; + 15: dout = 10; + + 16: dout = 3; + 17: dout = 13; + 18: dout = 4; + 19: dout = 7; + 20: dout = 15; + 21: dout = 2; + 22: dout = 8; + 23: dout = 14; + 24: dout = 12; + 25: dout = 0; + 26: dout = 1; + 27: dout = 10; + 28: dout = 6; + 29: dout = 9; + 30: dout = 11; + 31: dout = 5; + + 32: dout = 0; + 33: dout = 14; + 34: dout = 7; + 35: dout = 11; + 36: dout = 10; + 37: dout = 4; + 38: dout = 13; + 39: dout = 1; + 40: dout = 5; + 41: dout = 8; + 42: dout = 12; + 43: dout = 6; + 44: dout = 9; + 45: dout = 3; + 46: dout = 2; + 47: dout = 15; + + 48: dout = 13; + 49: dout = 8; + 50: dout = 10; + 51: dout = 1; + 52: dout = 3; + 53: dout = 15; + 54: dout = 4; + 55: dout = 2; + 56: dout = 11; + 57: dout = 6; + 58: dout = 7; + 59: dout = 12; + 60: dout = 0; + 61: dout = 5; + 62: dout = 14; + 63: dout = 9; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox3.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox3.v new file mode 100644 index 000000000..0c6cddf03 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox3.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox3(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 10; + 1: dout = 0; + 2: dout = 9; + 3: dout = 14; + 4: dout = 6; + 5: dout = 3; + 6: dout = 15; + 7: dout = 5; + 8: dout = 1; + 9: dout = 13; + 10: dout = 12; + 11: dout = 7; + 12: dout = 11; + 13: dout = 4; + 14: dout = 2; + 15: dout = 8; + + 16: dout = 13; + 17: dout = 7; + 18: dout = 0; + 19: dout = 9; + 20: dout = 3; + 21: dout = 4; + 22: dout = 6; + 23: dout = 10; + 24: dout = 2; + 25: dout = 8; + 26: dout = 5; + 27: dout = 14; + 28: dout = 12; + 29: dout = 11; + 30: dout = 15; + 31: dout = 1; + + 32: dout = 13; + 33: dout = 6; + 34: dout = 4; + 35: dout = 9; + 36: dout = 8; + 37: dout = 15; + 38: dout = 3; + 39: dout = 0; + 40: dout = 11; + 41: dout = 1; + 42: dout = 2; + 43: dout = 12; + 44: dout = 5; + 45: dout = 10; + 46: dout = 14; + 47: dout = 7; + + 48: dout = 1; + 49: dout = 10; + 50: dout = 13; + 51: dout = 0; + 52: dout = 6; + 53: dout = 9; + 54: dout = 8; + 55: dout = 7; + 56: dout = 4; + 57: dout = 15; + 58: dout = 14; + 59: dout = 3; + 60: dout = 11; + 61: dout = 5; + 62: dout = 2; + 63: dout = 12; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox4.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox4.v new file mode 100644 index 000000000..ec531c1e8 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox4.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox4(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 7; + 1: dout = 13; + 2: dout = 14; + 3: dout = 3; + 4: dout = 0; + 5: dout = 6; + 6: dout = 9; + 7: dout = 10; + 8: dout = 1; + 9: dout = 2; + 10: dout = 8; + 11: dout = 5; + 12: dout = 11; + 13: dout = 12; + 14: dout = 4; + 15: dout = 15; + + 16: dout = 13; + 17: dout = 8; + 18: dout = 11; + 19: dout = 5; + 20: dout = 6; + 21: dout = 15; + 22: dout = 0; + 23: dout = 3; + 24: dout = 4; + 25: dout = 7; + 26: dout = 2; + 27: dout = 12; + 28: dout = 1; + 29: dout = 10; + 30: dout = 14; + 31: dout = 9; + + 32: dout = 10; + 33: dout = 6; + 34: dout = 9; + 35: dout = 0; + 36: dout = 12; + 37: dout = 11; + 38: dout = 7; + 39: dout = 13; + 40: dout = 15; + 41: dout = 1; + 42: dout = 3; + 43: dout = 14; + 44: dout = 5; + 45: dout = 2; + 46: dout = 8; + 47: dout = 4; + + 48: dout = 3; + 49: dout = 15; + 50: dout = 0; + 51: dout = 6; + 52: dout = 10; + 53: dout = 1; + 54: dout = 13; + 55: dout = 8; + 56: dout = 9; + 57: dout = 4; + 58: dout = 5; + 59: dout = 11; + 60: dout = 12; + 61: dout = 7; + 62: dout = 2; + 63: dout = 14; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox5.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox5.v new file mode 100644 index 000000000..f874c25cc --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox5.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox5(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 2; + 1: dout = 12; + 2: dout = 4; + 3: dout = 1; + 4: dout = 7; + 5: dout = 10; + 6: dout = 11; + 7: dout = 6; + 8: dout = 8; + 9: dout = 5; + 10: dout = 3; + 11: dout = 15; + 12: dout = 13; + 13: dout = 0; + 14: dout = 14; + 15: dout = 9; + + 16: dout = 14; + 17: dout = 11; + 18: dout = 2; + 19: dout = 12; + 20: dout = 4; + 21: dout = 7; + 22: dout = 13; + 23: dout = 1; + 24: dout = 5; + 25: dout = 0; + 26: dout = 15; + 27: dout = 10; + 28: dout = 3; + 29: dout = 9; + 30: dout = 8; + 31: dout = 6; + + 32: dout = 4; + 33: dout = 2; + 34: dout = 1; + 35: dout = 11; + 36: dout = 10; + 37: dout = 13; + 38: dout = 7; + 39: dout = 8; + 40: dout = 15; + 41: dout = 9; + 42: dout = 12; + 43: dout = 5; + 44: dout = 6; + 45: dout = 3; + 46: dout = 0; + 47: dout = 14; + + 48: dout = 11; + 49: dout = 8; + 50: dout = 12; + 51: dout = 7; + 52: dout = 1; + 53: dout = 14; + 54: dout = 2; + 55: dout = 13; + 56: dout = 6; + 57: dout = 15; + 58: dout = 0; + 59: dout = 9; + 60: dout = 10; + 61: dout = 4; + 62: dout = 5; + 63: dout = 3; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox6.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox6.v new file mode 100644 index 000000000..58fc86af0 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox6.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox6(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 12; + 1: dout = 1; + 2: dout = 10; + 3: dout = 15; + 4: dout = 9; + 5: dout = 2; + 6: dout = 6; + 7: dout = 8; + 8: dout = 0; + 9: dout = 13; + 10: dout = 3; + 11: dout = 4; + 12: dout = 14; + 13: dout = 7; + 14: dout = 5; + 15: dout = 11; + + 16: dout = 10; + 17: dout = 15; + 18: dout = 4; + 19: dout = 2; + 20: dout = 7; + 21: dout = 12; + 22: dout = 9; + 23: dout = 5; + 24: dout = 6; + 25: dout = 1; + 26: dout = 13; + 27: dout = 14; + 28: dout = 0; + 29: dout = 11; + 30: dout = 3; + 31: dout = 8; + + 32: dout = 9; + 33: dout = 14; + 34: dout = 15; + 35: dout = 5; + 36: dout = 2; + 37: dout = 8; + 38: dout = 12; + 39: dout = 3; + 40: dout = 7; + 41: dout = 0; + 42: dout = 4; + 43: dout = 10; + 44: dout = 1; + 45: dout = 13; + 46: dout = 11; + 47: dout = 6; + + 48: dout = 4; + 49: dout = 3; + 50: dout = 2; + 51: dout = 12; + 52: dout = 9; + 53: dout = 5; + 54: dout = 15; + 55: dout = 10; + 56: dout = 11; + 57: dout = 14; + 58: dout = 1; + 59: dout = 7; + 60: dout = 6; + 61: dout = 0; + 62: dout = 8; + 63: dout = 13; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox7.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox7.v new file mode 100644 index 000000000..f27957e2f --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox7.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox7(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 4; + 1: dout = 11; + 2: dout = 2; + 3: dout = 14; + 4: dout = 15; + 5: dout = 0; + 6: dout = 8; + 7: dout = 13; + 8: dout = 3; + 9: dout = 12; + 10: dout = 9; + 11: dout = 7; + 12: dout = 5; + 13: dout = 10; + 14: dout = 6; + 15: dout = 1; + + 16: dout = 13; + 17: dout = 0; + 18: dout = 11; + 19: dout = 7; + 20: dout = 4; + 21: dout = 9; + 22: dout = 1; + 23: dout = 10; + 24: dout = 14; + 25: dout = 3; + 26: dout = 5; + 27: dout = 12; + 28: dout = 2; + 29: dout = 15; + 30: dout = 8; + 31: dout = 6; + + 32: dout = 1; + 33: dout = 4; + 34: dout = 11; + 35: dout = 13; + 36: dout = 12; + 37: dout = 3; + 38: dout = 7; + 39: dout = 14; + 40: dout = 10; + 41: dout = 15; + 42: dout = 6; + 43: dout = 8; + 44: dout = 0; + 45: dout = 5; + 46: dout = 9; + 47: dout = 2; + + 48: dout = 6; + 49: dout = 11; + 50: dout = 13; + 51: dout = 8; + 52: dout = 1; + 53: dout = 4; + 54: dout = 10; + 55: dout = 7; + 56: dout = 9; + 57: dout = 5; + 58: dout = 0; + 59: dout = 15; + 60: dout = 14; + 61: dout = 2; + 62: dout = 3; + 63: dout = 12; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox8.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox8.v new file mode 100644 index 000000000..5ebad6388 --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/sbox8.v @@ -0,0 +1,113 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SBOX //// +//// The SBOX is essentially a 64x4 ROM //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module sbox8(addr, dout); +input [1:6] addr; +output [1:4] dout; +reg [1:4] dout; + +always @(addr) begin + case ({addr[1], addr[6], addr[2:5]}) //synopsys full_case parallel_case + 0: dout = 13; + 1: dout = 2; + 2: dout = 8; + 3: dout = 4; + 4: dout = 6; + 5: dout = 15; + 6: dout = 11; + 7: dout = 1; + 8: dout = 10; + 9: dout = 9; + 10: dout = 3; + 11: dout = 14; + 12: dout = 5; + 13: dout = 0; + 14: dout = 12; + 15: dout = 7; + + 16: dout = 1; + 17: dout = 15; + 18: dout = 13; + 19: dout = 8; + 20: dout = 10; + 21: dout = 3; + 22: dout = 7; + 23: dout = 4; + 24: dout = 12; + 25: dout = 5; + 26: dout = 6; + 27: dout = 11; + 28: dout = 0; + 29: dout = 14; + 30: dout = 9; + 31: dout = 2; + + 32: dout = 7; + 33: dout = 11; + 34: dout = 4; + 35: dout = 1; + 36: dout = 9; + 37: dout = 12; + 38: dout = 14; + 39: dout = 2; + 40: dout = 0; + 41: dout = 6; + 42: dout = 10; + 43: dout = 13; + 44: dout = 15; + 45: dout = 3; + 46: dout = 5; + 47: dout = 8; + + 48: dout = 2; + 49: dout = 1; + 50: dout = 14; + 51: dout = 7; + 52: dout = 4; + 53: dout = 10; + 54: dout = 8; + 55: dout = 13; + 56: dout = 15; + 57: dout = 12; + 58: dout = 9; + 59: dout = 0; + 60: dout = 3; + 61: dout = 5; + 62: dout = 6; + 63: dout = 11; + + endcase + end + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_clockgen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_clockgen.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_clockgen.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_crc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_crc.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_crc.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_defines.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_fifo.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_fifo.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_fifo.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_maccontrol.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_maccontrol.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_maccontrol.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_macstatus.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_macstatus.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_macstatus.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_miim.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_miim.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_miim.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_outputcontrol.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_outputcontrol.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_outputcontrol.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_random.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_random.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_random.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_receivecontrol.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_receivecontrol.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_receivecontrol.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_register.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_register.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_register.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_registers.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_registers.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_registers.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxaddrcheck.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxaddrcheck.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxaddrcheck.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxcounters.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxcounters.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxcounters.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxethmac.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxethmac.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxethmac.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxstatem.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_rxstatem.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_rxstatem.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_shiftreg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_shiftreg.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_shiftreg.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_spram_256x32.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_spram_256x32.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_spram_256x32.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_top.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_transmitcontrol.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_transmitcontrol.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_transmitcontrol.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txcounters.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_txcounters.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txcounters.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txethmac.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_txethmac.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txethmac.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txstatem.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_txstatem.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_txstatem.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_wishbone.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_wishbone.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/eth_wishbone.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/timescale.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v b/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/xilinx_dist_ram_16x32.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/xilinx_dist_ram_16x32.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/rtl/xilinx_dist_ram_16x32.v diff --git a/openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v b/openfpga_flow/benchmarks/iwls2005/ethernet/testbench/eth_cop.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ethernet/eth_cop.v rename to openfpga_flow/benchmarks/iwls2005/ethernet/testbench/eth_cop.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/except.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/except.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/except.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/except.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/fpu.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/fpu.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/fpu.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/fpu.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/post_norm.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/post_norm.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/post_norm.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/post_norm.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/pre_norm.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/pre_norm.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/pre_norm.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/pre_norm_fmul.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/pre_norm_fmul.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/pre_norm_fmul.v diff --git a/openfpga_flow/benchmarks/iwls2005/fpu/primitives.v b/openfpga_flow/benchmarks/iwls2005/fpu/rtl/primitives.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/fpu/primitives.v rename to openfpga_flow/benchmarks/iwls2005/fpu/rtl/primitives.v diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v b/openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_bit_ctrl.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_bit_ctrl.v rename to openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_bit_ctrl.v diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v b/openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_byte_ctrl.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_byte_ctrl.v rename to openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_byte_ctrl.v diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v b/openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_defines.v rename to openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v b/openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/i2c/i2c_master_top.v rename to openfpga_flow/benchmarks/iwls2005/i2c/rtl/i2c_master_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/i2c/timescale.v b/openfpga_flow/benchmarks/iwls2005/i2c/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/i2c/timescale.v rename to openfpga_flow/benchmarks/iwls2005/i2c/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_adr_sel.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_adr_sel.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_adr_sel.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_cs_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_cs_rf.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_cs_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_defines.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_dp.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_dp.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_dp.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_incn_r.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_incn_r.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_incn_r.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_mem_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_mem_if.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_mem_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_obct.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_obct.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_obct_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_obct_top.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_obct_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_rd_fifo.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rd_fifo.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_rd_fifo.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_refresh.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_refresh.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_refresh.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_rf.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_timing.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_timing.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_timing.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_top.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v b/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_wb_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/mem_ctrl/mc_wb_if.v rename to openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_wb_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/bus_commands.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/bus_commands.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/bus_commands.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_async_reset_flop.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_async_reset_flop.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_async_reset_flop.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_bridge32.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_bridge32.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_bridge32.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_cbe_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_cbe_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_cbe_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_conf_cyc_addr_dec.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_conf_cyc_addr_dec.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_conf_cyc_addr_dec.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_conf_space.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_conf_space.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_conf_space.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_constants.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_constants.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_constants.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_cur_out_reg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_cur_out_reg.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_cur_out_reg.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_delayed_sync.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_sync.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_delayed_sync.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_delayed_write_reg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_delayed_write_reg.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_delayed_write_reg.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_frame_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_frame_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_load_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_frame_load_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_frame_load_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_in_reg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_in_reg.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_in_reg.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux_ad_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux_ad_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux_ad_load_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_io_mux_ad_load_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_io_mux_ad_load_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_irdy_out_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_irdy_out_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_irdy_out_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ad_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ad_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ad_load_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ad_load_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ad_load_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ch_state_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_mas_ch_state_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_mas_ch_state_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_master32_sm.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_master32_sm.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_master32_sm_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_master32_sm_if.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_master32_sm_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_out_reg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_out_reg.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_out_reg.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_par_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_par_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_par_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_parity_check.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_parity_check.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_parity_check.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pci_decoder.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_pci_decoder.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pci_decoder.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pci_tpram.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_pci_tpram.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pci_tpram.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pcir_fifo_control.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pcir_fifo_control.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_pcir_fifo_control.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pcir_fifo_control.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_fifo_control.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pciw_fifo_control.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_fifo_control.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pciw_fifo_control.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_pcir_fifos.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pciw_pcir_fifos.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_pciw_pcir_fifos.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_pciw_pcir_fifos.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_perr_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_perr_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_perr_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_perr_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_perr_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_perr_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_perr_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_perr_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_ram_16x40d.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_ram_16x40d.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_ram_16x40d.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_ram_16x40d.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_rst_int.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_rst_int.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_rst_int.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_rst_int.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_serr_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_serr_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_serr_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_serr_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_serr_en_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_serr_en_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_serr_en_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_serr_en_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_spoci_ctrl.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_spoci_ctrl.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_spoci_ctrl.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_spoci_ctrl.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_sync_module.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_sync_module.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_sync_module.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_synchronizer_flop.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_synchronizer_flop.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_synchronizer_flop.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_clk_en.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_clk_en.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_clk_en.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_devs_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_devs_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_devs_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_interface.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_interface.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_interface.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_sm.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_sm.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_sm.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_stop_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_stop_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_stop_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_trdy_crit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target32_trdy_crit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target32_trdy_crit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target_unit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_target_unit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_target_unit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_user_constants.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_user_constants.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_user_constants.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_addr_mux.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_addr_mux.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_addr_mux.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_decoder.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_decoder.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_decoder.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_master.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_master.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_master.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_slave.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_slave.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_slave_unit.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_slave_unit.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_slave_unit.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_tpram.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wb_tpram.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wb_tpram.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wbr_fifo_control.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbr_fifo_control.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wbr_fifo_control.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbr_fifo_control.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wbs_wbb3_2_wbb2.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbs_wbb3_2_wbb2.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wbs_wbb3_2_wbb2.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbs_wbb3_2_wbb2.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_fifo_control.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbw_fifo_control.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_fifo_control.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbw_fifo_control.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_wbr_fifos.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbw_wbr_fifos.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/pci_wbw_wbr_fifos.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/pci_wbw_wbr_fifos.v diff --git a/openfpga_flow/benchmarks/iwls2005/pci/timescale.v b/openfpga_flow/benchmarks/iwls2005/pci/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/pci/timescale.v rename to openfpga_flow/benchmarks/iwls2005/pci/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/sasc/sasc_brg.v b/openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_brg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/sasc/sasc_brg.v rename to openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_brg.v diff --git a/openfpga_flow/benchmarks/iwls2005/sasc/sasc_fifo4.v b/openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_fifo4.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/sasc/sasc_fifo4.v rename to openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_fifo4.v diff --git a/openfpga_flow/benchmarks/iwls2005/sasc/sasc_top.v b/openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/sasc/sasc_top.v rename to openfpga_flow/benchmarks/iwls2005/sasc/rtl/sasc_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/sasc/timescale.v b/openfpga_flow/benchmarks/iwls2005/sasc/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/sasc/timescale.v rename to openfpga_flow/benchmarks/iwls2005/sasc/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/simple_spi/fifo4.v b/openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/fifo4.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/simple_spi/fifo4.v rename to openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/fifo4.v diff --git a/openfpga_flow/benchmarks/iwls2005/simple_spi/simple_spi_top.v b/openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/simple_spi_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/simple_spi/simple_spi_top.v rename to openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/simple_spi_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/spi/spi_clgen.v b/openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_clgen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/spi/spi_clgen.v rename to openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_clgen.v diff --git a/openfpga_flow/benchmarks/iwls2005/spi/spi_defines.v b/openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/spi/spi_defines.v rename to openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/spi/spi_shift.v b/openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_shift.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/spi/spi_shift.v rename to openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_shift.v diff --git a/openfpga_flow/benchmarks/iwls2005/spi/spi_top.v b/openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/spi/spi_top.v rename to openfpga_flow/benchmarks/iwls2005/spi/rtl/spi_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/spi/timescale.v b/openfpga_flow/benchmarks/iwls2005/spi/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/spi/timescale.v rename to openfpga_flow/benchmarks/iwls2005/spi/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/ss_pcm/pcm_slv_top.v b/openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/pcm_slv_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ss_pcm/pcm_slv_top.v rename to openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/pcm_slv_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/ss_pcm/timescale.v b/openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/ss_pcm/timescale.v rename to openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/steppermotordrive/StepperMotorDrive.vhd b/openfpga_flow/benchmarks/iwls2005/steppermotordrive/rtl/StepperMotorDrive.vhd similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/steppermotordrive/StepperMotorDrive.vhd rename to openfpga_flow/benchmarks/iwls2005/steppermotordrive/rtl/StepperMotorDrive.vhd diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/aes.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/aes.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/aes.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/byte_mixcolum.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/byte_mixcolum.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/byte_mixcolum.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/keysched.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/keysched.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/keysched.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/mixcolum.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/mixcolum.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/mixcolum.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/sbox.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/sbox.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/sbox.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/subbytes.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/subbytes.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/subbytes.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/timescale.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v b/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/word_mixcolum.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcaes/word_mixcolum.v rename to openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/word_mixcolum.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/des.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/des.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/des.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/des.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/desround.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/desround.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/desround.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/key_gen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/key_gen.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/key_gen.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s1.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s1.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s1.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s2.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s2.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s2.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s3.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s3.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s3.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s4.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s4.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s4.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s5.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s5.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s5.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s6.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s6.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s6.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s7.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s7.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s7.v diff --git a/openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v b/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s8.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/systemcdes/s8.v rename to openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/s8.v diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v b/openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_alu.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/tv80/tv80_alu.v rename to openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_alu.v diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v b/openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_core.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/tv80/tv80_core.v rename to openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_core.v diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v b/openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_mcode.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/tv80/tv80_mcode.v rename to openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_mcode.v diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v b/openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_reg.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/tv80/tv80_reg.v rename to openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80_reg.v diff --git a/openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v b/openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80s.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/tv80/tv80s.v rename to openfpga_flow/benchmarks/iwls2005/tv80/rtl/tv80s.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_crc16.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc16.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_crc16.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_crc5.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_crc5.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_crc5.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_defines.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_ep_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_ep_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_ep_rf_dummy.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_ep_rf_dummy.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_ep_rf_dummy.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_idma.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_idma.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_idma.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_mem_arb.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_mem_arb.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_mem_arb.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pa.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pa.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pa.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pd.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pd.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pd.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pe.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pe.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pe.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pl.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_pl.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pl.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_rf.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_top.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_if.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_utmi_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_if.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_utmi_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_ls.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_utmi_ls.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_utmi_ls.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_utmi_ls.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v b/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_wb.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_funct/usbf_wb.v rename to openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_wb.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_phy/timescale.v rename to openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_phy.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_phy/usb_phy.v rename to openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_phy.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_rx_phy.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_phy/usb_rx_phy.v rename to openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_rx_phy.v diff --git a/openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v b/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_tx_phy.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/usb_phy/usb_tx_phy.v rename to openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/usb_tx_phy.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/generic_dpram.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_dpram.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/generic_dpram.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_spram.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/generic_spram.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/generic_spram.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/generic_spram.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/timescale.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/timescale.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/timescale.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/timescale.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_clkgen.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_clkgen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_clkgen.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_clkgen.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_colproc.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_colproc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_colproc.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_colproc.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_csm_pb.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_csm_pb.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_csm_pb.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_csm_pb.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_cur_cregs.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_cur_cregs.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_cur_cregs.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_cur_cregs.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_curproc.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_curproc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_curproc.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_curproc.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_defines.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_enh_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_enh_top.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_enh_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_fifo.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_fifo.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo_dc.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_fifo_dc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_fifo_dc.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_fifo_dc.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_pgen.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_pgen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_pgen.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_pgen.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_tgen.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_tgen.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_tgen.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_tgen.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_vtim.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_vtim.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_vtim.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_vtim.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_master.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_wb_master.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_master.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_wb_master.v diff --git a/openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v b/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_wb_slave.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/vga_lcd/vga_wb_slave.v rename to openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_wb_slave.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_arb.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_arb.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_arb.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_defines.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_master_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_master_if.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_master_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_msel.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_msel.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_msel.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_pri_dec.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_dec.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_pri_dec.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_pri_enc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_pri_enc.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_pri_enc.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_rf.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_slave_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_slave_if.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_slave_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v b/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_conmax/wb_conmax_top.v rename to openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/wb_conmax_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_arb.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_arb.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_arb.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_pri_enc.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_pri_enc.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_pri_enc.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_rf.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_sel.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_ch_sel.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_ch_sel.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_de.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_de.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_de.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_defines.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_defines.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_defines.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_inc30r.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_inc30r.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_inc30r.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_pri_enc_sub.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_pri_enc_sub.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_pri_enc_sub.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_rf.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_rf.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_rf.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_top.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_top.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_top.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_if.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_if.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_if.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_mast.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_mast.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_mast.v diff --git a/openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v b/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_slv.v similarity index 100% rename from openfpga_flow/benchmarks/iwls2005/wb_dma/wb_dma_wb_slv.v rename to openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/wb_dma_wb_slv.v From 43bf016576b4a1d7dd51c5d30930e12b539a2552 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:09:47 -0600 Subject: [PATCH 124/352] [Script] Add example openfpga shell script for iwls benchmark --- .../iwls_benchmark_example_script.openfpga | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga new file mode 100644 index 000000000..04089a450 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga @@ -0,0 +1,60 @@ +# Run VPR for the 'and' design +# When the global clock is defined as a port of a tile, clock routing in VPR should be skipped +# This is due to the Fc_in of clock port is set to 0 for global wiring +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --route_chan_width ${VPR_ROUTE_CHAN_WIDTH} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +# Note: no need to assign activity file when you used a fixed number +# of clock cycles in simulation settings +# Also, ACE2 does not support multiple clocks +# Therefore, activity file is not recommended for multi-clock fabric/implementations +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup #--verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enabled frame view creation to save runtime and memory +# Note that this is turned on when bitstream generation +# is the ONLY purpose of the flow!!! +build_fabric --compress_routing --frame_view #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 1566a5558ac23074e5dc071773b38a8332bcae66 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:10:31 -0600 Subject: [PATCH 125/352] [Test] Add task configuration file for iwls2005 --- .../benchmark_sweep/iwls2005/config/task.conf | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf diff --git a/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf b/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf new file mode 100644 index 000000000..60eaeec4a --- /dev/null +++ b/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf @@ -0,0 +1,103 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +# VPR parameters +# Use a fixed routing channel width to save runtime +vpr_route_chan_width=300 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml + +[BENCHMARKS] +# RTL netlists from IWLS 2005 benchmark release +# Comment out due to DFF synthesis problems +#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/*.v +#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/*.v +#bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/*.v +#bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/*.v +# Comment out due to VHDL is not supported by Yosys without Verific +#bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/steppermotordrive/rtl/*.vhd +bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/tv80/rtl/*.v +# Comment out due to DFF synthesis problems +#bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/*.v +# AES core has two top modules that can be tested: encryption and decryption +# Synthesis is too long; skip it +#bench7=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/*.v +#bench8=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/*.v +#bench9=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/fpu/rtl/*.v +# Comment out due to DFF synthesis problems +#bench10=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/pci/rtl/*.v +#bench11=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/spi/rtl/*.v +#bench12=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/*.v +bench13=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/*.v +# Comment out due to DFF synthesis problems +#bench14=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/*.v +## DES has two versions: area-optimized and performance optimized +bench15=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/*.v +bench16=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/*.v +# Comment out due to DFF synthesis problems +#bench17=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/i2c/rtl/*.v +# Comment out due to DFF synthesis problems +#bench18=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/sasc/rtl/*.v +bench19=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/*.v +# Comment out due to DFF synthesis problems +#bench20=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/*.v +bench21=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/*.v +# Comment out due to DFF synthesis problems +#bench22=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/*.v + +[SYNTHESIS_PARAM] +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys +bench0_top = ac97_top +bench1_top = eth_top +bench2_top = mc_top +bench3_top = simple_spi_top +bench4_top = StepperMotorPorts +bench5_top = tv80s +bench6_top = vga_enh_top +bench7_top = aes_cipher_top +bench8_top = aes_inv_cipher_top +bench9_top = fpu +bench10_top = pci_bridge32 +bench11_top = spi_top +bench12_top = aes +bench13_top = usbf_top +bench14_top = wb_conmax_top +# Not sure either des or des3 is the top module. Need further investigation +bench15_top = des +bench16_top = des3 +bench17_top = i2c_master_top +bench18_top = sasc_top +bench19_top = pcm_slv_top +# May conflict with the top module name with other 'des' benchmark; This is a bug of openfpga flow scripts +bench20_top = des +bench21_top = usb_phy +bench22_top = wb_dma_top + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From 87587bbb74fbd7259eaad966a128b1348d9925f7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:12:05 -0600 Subject: [PATCH 126/352] [Test] Add iwls2005 benchmarks to regression tests --- .../iwls_benchmark_reg_test.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 openfpga_flow/regression_test_scripts/iwls_benchmark_reg_test.sh diff --git a/openfpga_flow/regression_test_scripts/iwls_benchmark_reg_test.sh b/openfpga_flow/regression_test_scripts/iwls_benchmark_reg_test.sh new file mode 100755 index 000000000..6bbb44633 --- /dev/null +++ b/openfpga_flow/regression_test_scripts/iwls_benchmark_reg_test.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +source openfpga.sh +PYTHON_EXEC=python3.8 +############################################### +# OpenFPGA Shell with VPR8 +############################################## +echo -e "IWLS'05 benchmark regression tests"; +run-task benchmark_sweep/iwls2005 --debug --show_thread_logs +# Run a quick but relaxed QoR check for heterogeneous blocks +#python3 openfpga_flow/scripts/check_qor.py --reference_csv_file openfpga_flow/tasks/benchmark_sweep/vtr_benchmarks/config/vtr_benchmark_golden_results.csv --check_csv_file openfpga_flow/tasks/benchmark_sweep/vtr_benchmarks/latest/task_result.csv --metric_checklist_csv_file openfpga_flow/tasks/benchmark_sweep/vtr_benchmarks/config/metric_checklist.csv --check_tolerance 0.2,100 From f395ed2718c6d40556af445541bc904d0f6fde3e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:13:46 -0600 Subject: [PATCH 127/352] [Test] Deploy iwls tests to CI --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 90ee24e72..753b4c77f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,6 +212,7 @@ jobs: - name: fpga_spice_reg_test - name: quicklogic_reg_test - name: vtr_benchmark_reg_test + - name: iwls_benchmark_reg_test steps: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 @@ -258,6 +259,7 @@ jobs: - name: fpga_spice_reg_test - name: quicklogic_reg_test - name: vtr_benchmark_reg_test + - name: iwls_benchmark_reg_test steps: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 From e46c6e75a3c6a0ef68381bcefc0aaf6706fd105d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 16:50:41 -0600 Subject: [PATCH 128/352] [Benchmark] Add missing RTL for IWLS2005 benchmarks --- .../iwls2005/des/perf_opt/rtl/crp.v | 69 ++ .../iwls2005/des/perf_opt/rtl/key_sel3.v | 865 ++++++++++++++++++ 2 files changed, 934 insertions(+) create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/crp.v create mode 100644 openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel3.v diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/crp.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/crp.v new file mode 100644 index 000000000..5985f2f1a --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/crp.v @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// CRP //// +//// DES Crypt Module //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module crp(P, R, K_sub); +output [1:32] P; +input [1:32] R; +input [1:48] K_sub; + +wire [1:48] E; +wire [1:48] X; +wire [1:32] S; + +assign E[1:48] = { R[32], R[1], R[2], R[3], R[4], R[5], R[4], R[5], + R[6], R[7], R[8], R[9], R[8], R[9], R[10], R[11], + R[12], R[13], R[12], R[13], R[14], R[15], R[16], + R[17], R[16], R[17], R[18], R[19], R[20], R[21], + R[20], R[21], R[22], R[23], R[24], R[25], R[24], + R[25], R[26], R[27], R[28], R[29], R[28], R[29], + R[30], R[31], R[32], R[1]}; + +assign X = E ^ K_sub; + +sbox1 u0( .addr(X[01:06]), .dout(S[01:04]) ); +sbox2 u1( .addr(X[07:12]), .dout(S[05:08]) ); +sbox3 u2( .addr(X[13:18]), .dout(S[09:12]) ); +sbox4 u3( .addr(X[19:24]), .dout(S[13:16]) ); +sbox5 u4( .addr(X[25:30]), .dout(S[17:20]) ); +sbox6 u5( .addr(X[31:36]), .dout(S[21:24]) ); +sbox7 u6( .addr(X[37:42]), .dout(S[25:28]) ); +sbox8 u7( .addr(X[43:48]), .dout(S[29:32]) ); + +assign P[1:32] = { S[16], S[7], S[20], S[21], S[29], S[12], S[28], + S[17], S[1], S[15], S[23], S[26], S[5], S[18], + S[31], S[10], S[2], S[8], S[24], S[14], S[32], + S[27], S[3], S[9], S[19], S[13], S[30], S[6], + S[22], S[11], S[4], S[25]}; + +endmodule diff --git a/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel3.v b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel3.v new file mode 100644 index 000000000..9f232c41d --- /dev/null +++ b/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/key_sel3.v @@ -0,0 +1,865 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// KEY_SEL //// +//// Select one of 16 sub-keys for round //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +module key_sel3(K_sub, key1, key2, key3, roundSel, decrypt); +output [1:48] K_sub; +input [55:0] key1, key2, key3; +input [5:0] roundSel; +input decrypt; + +wire decrypt_int; +reg [55:0] K; +reg [1:48] K_sub; +wire [1:48] K1, K2, K3, K4, K5, K6, K7, K8, K9; +wire [1:48] K10, K11, K12, K13, K14, K15, K16; + +always @(roundSel or decrypt or key1 or key2 or key3) + case ({decrypt, roundSel[5:4]}) // synopsys full_case parallel_case + 3'b0_00: K = key1; + 3'b0_01: K = key2; + 3'b0_10: K = key3; + 3'b1_00: K = key3; + 3'b1_01: K = key2; + 3'b1_10: K = key1; + endcase + +assign decrypt_int = (roundSel[5:4]==2'h1) ? !decrypt : decrypt; + +always @(K1 or K2 or K3 or K4 or K5 or K6 or K7 or K8 or K9 or K10 + or K11 or K12 or K13 or K14 or K15 or K16 or roundSel) + case(roundSel[3:0]) // synopsys full_case parallel_case + 0: K_sub = K1; + 1: K_sub = K2; + 2: K_sub = K3; + 3: K_sub = K4; + 4: K_sub = K5; + 5: K_sub = K6; + 6: K_sub = K7; + 7: K_sub = K8; + 8: K_sub = K9; + 9: K_sub = K10; + 10: K_sub = K11; + 11: K_sub = K12; + 12: K_sub = K13; + 13: K_sub = K14; + 14: K_sub = K15; + 15: K_sub = K16; + endcase + + +assign K16[1] = decrypt_int ? K[47] : K[40]; +assign K16[2] = decrypt_int ? K[11] : K[4]; +assign K16[3] = decrypt_int ? K[26] : K[19]; +assign K16[4] = decrypt_int ? K[3] : K[53]; +assign K16[5] = decrypt_int ? K[13] : K[6]; +assign K16[6] = decrypt_int ? K[41] : K[34]; +assign K16[7] = decrypt_int ? K[27] : K[20]; +assign K16[8] = decrypt_int ? K[6] : K[24]; +assign K16[9] = decrypt_int ? K[54] : K[47]; +assign K16[10] = decrypt_int ? K[48] : K[41]; +assign K16[11] = decrypt_int ? K[39] : K[32]; +assign K16[12] = decrypt_int ? K[19] : K[12]; +assign K16[13] = decrypt_int ? K[53] : K[46]; +assign K16[14] = decrypt_int ? K[25] : K[18]; +assign K16[15] = decrypt_int ? K[33] : K[26]; +assign K16[16] = decrypt_int ? K[34] : K[27]; +assign K16[17] = decrypt_int ? K[17] : K[10]; +assign K16[18] = decrypt_int ? K[5] : K[55]; +assign K16[19] = decrypt_int ? K[4] : K[54]; +assign K16[20] = decrypt_int ? K[55] : K[48]; +assign K16[21] = decrypt_int ? K[24] : K[17]; +assign K16[22] = decrypt_int ? K[32] : K[25]; +assign K16[23] = decrypt_int ? K[40] : K[33]; +assign K16[24] = decrypt_int ? K[20] : K[13]; +assign K16[25] = decrypt_int ? K[36] : K[29]; +assign K16[26] = decrypt_int ? K[31] : K[51]; +assign K16[27] = decrypt_int ? K[21] : K[14]; +assign K16[28] = decrypt_int ? K[8] : K[1]; +assign K16[29] = decrypt_int ? K[23] : K[16]; +assign K16[30] = decrypt_int ? K[52] : K[45]; +assign K16[31] = decrypt_int ? K[14] : K[7]; +assign K16[32] = decrypt_int ? K[29] : K[22]; +assign K16[33] = decrypt_int ? K[51] : K[44]; +assign K16[34] = decrypt_int ? K[9] : K[2]; +assign K16[35] = decrypt_int ? K[35] : K[28]; +assign K16[36] = decrypt_int ? K[30] : K[23]; +assign K16[37] = decrypt_int ? K[2] : K[50]; +assign K16[38] = decrypt_int ? K[37] : K[30]; +assign K16[39] = decrypt_int ? K[22] : K[15]; +assign K16[40] = decrypt_int ? K[0] : K[52]; +assign K16[41] = decrypt_int ? K[42] : K[35]; +assign K16[42] = decrypt_int ? K[38] : K[31]; +assign K16[43] = decrypt_int ? K[16] : K[9]; +assign K16[44] = decrypt_int ? K[43] : K[36]; +assign K16[45] = decrypt_int ? K[44] : K[37]; +assign K16[46] = decrypt_int ? K[1] : K[49]; +assign K16[47] = decrypt_int ? K[7] : K[0]; +assign K16[48] = decrypt_int ? K[28] : K[21]; + +assign K15[1] = decrypt_int ? K[54] : K[33]; +assign K15[2] = decrypt_int ? K[18] : K[54]; +assign K15[3] = decrypt_int ? K[33] : K[12]; +assign K15[4] = decrypt_int ? K[10] : K[46]; +assign K15[5] = decrypt_int ? K[20] : K[24]; +assign K15[6] = decrypt_int ? K[48] : K[27]; +assign K15[7] = decrypt_int ? K[34] : K[13]; +assign K15[8] = decrypt_int ? K[13] : K[17]; +assign K15[9] = decrypt_int ? K[4] : K[40]; +assign K15[10] = decrypt_int ? K[55] : K[34]; +assign K15[11] = decrypt_int ? K[46] : K[25]; +assign K15[12] = decrypt_int ? K[26] : K[5]; +assign K15[13] = decrypt_int ? K[3] : K[39]; +assign K15[14] = decrypt_int ? K[32] : K[11]; +assign K15[15] = decrypt_int ? K[40] : K[19]; +assign K15[16] = decrypt_int ? K[41] : K[20]; +assign K15[17] = decrypt_int ? K[24] : K[3]; +assign K15[18] = decrypt_int ? K[12] : K[48]; +assign K15[19] = decrypt_int ? K[11] : K[47]; +assign K15[20] = decrypt_int ? K[5] : K[41]; +assign K15[21] = decrypt_int ? K[6] : K[10]; +assign K15[22] = decrypt_int ? K[39] : K[18]; +assign K15[23] = decrypt_int ? K[47] : K[26]; +assign K15[24] = decrypt_int ? K[27] : K[6]; +assign K15[25] = decrypt_int ? K[43] : K[22]; +assign K15[26] = decrypt_int ? K[38] : K[44]; +assign K15[27] = decrypt_int ? K[28] : K[7]; +assign K15[28] = decrypt_int ? K[15] : K[49]; +assign K15[29] = decrypt_int ? K[30] : K[9]; +assign K15[30] = decrypt_int ? K[0] : K[38]; +assign K15[31] = decrypt_int ? K[21] : K[0]; +assign K15[32] = decrypt_int ? K[36] : K[15]; +assign K15[33] = decrypt_int ? K[31] : K[37]; +assign K15[34] = decrypt_int ? K[16] : K[50]; +assign K15[35] = decrypt_int ? K[42] : K[21]; +assign K15[36] = decrypt_int ? K[37] : K[16]; +assign K15[37] = decrypt_int ? K[9] : K[43]; +assign K15[38] = decrypt_int ? K[44] : K[23]; +assign K15[39] = decrypt_int ? K[29] : K[8]; +assign K15[40] = decrypt_int ? K[7] : K[45]; +assign K15[41] = decrypt_int ? K[49] : K[28]; +assign K15[42] = decrypt_int ? K[45] : K[51]; +assign K15[43] = decrypt_int ? K[23] : K[2]; +assign K15[44] = decrypt_int ? K[50] : K[29]; +assign K15[45] = decrypt_int ? K[51] : K[30]; +assign K15[46] = decrypt_int ? K[8] : K[42]; +assign K15[47] = decrypt_int ? K[14] : K[52]; +assign K15[48] = decrypt_int ? K[35] : K[14]; + +assign K14[1] = decrypt_int ? K[11] : K[19]; +assign K14[2] = decrypt_int ? K[32] : K[40]; +assign K14[3] = decrypt_int ? K[47] : K[55]; +assign K14[4] = decrypt_int ? K[24] : K[32]; +assign K14[5] = decrypt_int ? K[34] : K[10]; +assign K14[6] = decrypt_int ? K[5] : K[13]; +assign K14[7] = decrypt_int ? K[48] : K[24]; +assign K14[8] = decrypt_int ? K[27] : K[3]; +assign K14[9] = decrypt_int ? K[18] : K[26]; +assign K14[10] = decrypt_int ? K[12] : K[20]; +assign K14[11] = decrypt_int ? K[3] : K[11]; +assign K14[12] = decrypt_int ? K[40] : K[48]; +assign K14[13] = decrypt_int ? K[17] : K[25]; +assign K14[14] = decrypt_int ? K[46] : K[54]; +assign K14[15] = decrypt_int ? K[54] : K[5]; +assign K14[16] = decrypt_int ? K[55] : K[6]; +assign K14[17] = decrypt_int ? K[13] : K[46]; +assign K14[18] = decrypt_int ? K[26] : K[34]; +assign K14[19] = decrypt_int ? K[25] : K[33]; +assign K14[20] = decrypt_int ? K[19] : K[27]; +assign K14[21] = decrypt_int ? K[20] : K[53]; +assign K14[22] = decrypt_int ? K[53] : K[4]; +assign K14[23] = decrypt_int ? K[4] : K[12]; +assign K14[24] = decrypt_int ? K[41] : K[17]; +assign K14[25] = decrypt_int ? K[2] : K[8]; +assign K14[26] = decrypt_int ? K[52] : K[30]; +assign K14[27] = decrypt_int ? K[42] : K[52]; +assign K14[28] = decrypt_int ? K[29] : K[35]; +assign K14[29] = decrypt_int ? K[44] : K[50]; +assign K14[30] = decrypt_int ? K[14] : K[51]; +assign K14[31] = decrypt_int ? K[35] : K[45]; +assign K14[32] = decrypt_int ? K[50] : K[1]; +assign K14[33] = decrypt_int ? K[45] : K[23]; +assign K14[34] = decrypt_int ? K[30] : K[36]; +assign K14[35] = decrypt_int ? K[1] : K[7]; +assign K14[36] = decrypt_int ? K[51] : K[2]; +assign K14[37] = decrypt_int ? K[23] : K[29]; +assign K14[38] = decrypt_int ? K[31] : K[9]; +assign K14[39] = decrypt_int ? K[43] : K[49]; +assign K14[40] = decrypt_int ? K[21] : K[31]; +assign K14[41] = decrypt_int ? K[8] : K[14]; +assign K14[42] = decrypt_int ? K[0] : K[37]; +assign K14[43] = decrypt_int ? K[37] : K[43]; +assign K14[44] = decrypt_int ? K[9] : K[15]; +assign K14[45] = decrypt_int ? K[38] : K[16]; +assign K14[46] = decrypt_int ? K[22] : K[28]; +assign K14[47] = decrypt_int ? K[28] : K[38]; +assign K14[48] = decrypt_int ? K[49] : K[0]; + +assign K13[1] = decrypt_int ? K[25] : K[5]; +assign K13[2] = decrypt_int ? K[46] : K[26]; +assign K13[3] = decrypt_int ? K[4] : K[41]; +assign K13[4] = decrypt_int ? K[13] : K[18]; +assign K13[5] = decrypt_int ? K[48] : K[53]; +assign K13[6] = decrypt_int ? K[19] : K[24]; +assign K13[7] = decrypt_int ? K[5] : K[10]; +assign K13[8] = decrypt_int ? K[41] : K[46]; +assign K13[9] = decrypt_int ? K[32] : K[12]; +assign K13[10] = decrypt_int ? K[26] : K[6]; +assign K13[11] = decrypt_int ? K[17] : K[54]; +assign K13[12] = decrypt_int ? K[54] : K[34]; +assign K13[13] = decrypt_int ? K[6] : K[11]; +assign K13[14] = decrypt_int ? K[3] : K[40]; +assign K13[15] = decrypt_int ? K[11] : K[48]; +assign K13[16] = decrypt_int ? K[12] : K[17]; +assign K13[17] = decrypt_int ? K[27] : K[32]; +assign K13[18] = decrypt_int ? K[40] : K[20]; +assign K13[19] = decrypt_int ? K[39] : K[19]; +assign K13[20] = decrypt_int ? K[33] : K[13]; +assign K13[21] = decrypt_int ? K[34] : K[39]; +assign K13[22] = decrypt_int ? K[10] : K[47]; +assign K13[23] = decrypt_int ? K[18] : K[55]; +assign K13[24] = decrypt_int ? K[55] : K[3]; +assign K13[25] = decrypt_int ? K[16] : K[49]; +assign K13[26] = decrypt_int ? K[7] : K[16]; +assign K13[27] = decrypt_int ? K[1] : K[38]; +assign K13[28] = decrypt_int ? K[43] : K[21]; +assign K13[29] = decrypt_int ? K[31] : K[36]; +assign K13[30] = decrypt_int ? K[28] : K[37]; +assign K13[31] = decrypt_int ? K[49] : K[31]; +assign K13[32] = decrypt_int ? K[9] : K[42]; +assign K13[33] = decrypt_int ? K[0] : K[9]; +assign K13[34] = decrypt_int ? K[44] : K[22]; +assign K13[35] = decrypt_int ? K[15] : K[52]; +assign K13[36] = decrypt_int ? K[38] : K[43]; +assign K13[37] = decrypt_int ? K[37] : K[15]; +assign K13[38] = decrypt_int ? K[45] : K[50]; +assign K13[39] = decrypt_int ? K[2] : K[35]; +assign K13[40] = decrypt_int ? K[35] : K[44]; +assign K13[41] = decrypt_int ? K[22] : K[0]; +assign K13[42] = decrypt_int ? K[14] : K[23]; +assign K13[43] = decrypt_int ? K[51] : K[29]; +assign K13[44] = decrypt_int ? K[23] : K[1]; +assign K13[45] = decrypt_int ? K[52] : K[2]; +assign K13[46] = decrypt_int ? K[36] : K[14]; +assign K13[47] = decrypt_int ? K[42] : K[51]; +assign K13[48] = decrypt_int ? K[8] : K[45]; + +assign K12[1] = decrypt_int ? K[39] : K[48]; +assign K12[2] = decrypt_int ? K[3] : K[12]; +assign K12[3] = decrypt_int ? K[18] : K[27]; +assign K12[4] = decrypt_int ? K[27] : K[4]; +assign K12[5] = decrypt_int ? K[5] : K[39]; +assign K12[6] = decrypt_int ? K[33] : K[10]; +assign K12[7] = decrypt_int ? K[19] : K[53]; +assign K12[8] = decrypt_int ? K[55] : K[32]; +assign K12[9] = decrypt_int ? K[46] : K[55]; +assign K12[10] = decrypt_int ? K[40] : K[17]; +assign K12[11] = decrypt_int ? K[6] : K[40]; +assign K12[12] = decrypt_int ? K[11] : K[20]; +assign K12[13] = decrypt_int ? K[20] : K[54]; +assign K12[14] = decrypt_int ? K[17] : K[26]; +assign K12[15] = decrypt_int ? K[25] : K[34]; +assign K12[16] = decrypt_int ? K[26] : K[3]; +assign K12[17] = decrypt_int ? K[41] : K[18]; +assign K12[18] = decrypt_int ? K[54] : K[6]; +assign K12[19] = decrypt_int ? K[53] : K[5]; +assign K12[20] = decrypt_int ? K[47] : K[24]; +assign K12[21] = decrypt_int ? K[48] : K[25]; +assign K12[22] = decrypt_int ? K[24] : K[33]; +assign K12[23] = decrypt_int ? K[32] : K[41]; +assign K12[24] = decrypt_int ? K[12] : K[46]; +assign K12[25] = decrypt_int ? K[30] : K[35]; +assign K12[26] = decrypt_int ? K[21] : K[2]; +assign K12[27] = decrypt_int ? K[15] : K[51]; +assign K12[28] = decrypt_int ? K[2] : K[7]; +assign K12[29] = decrypt_int ? K[45] : K[22]; +assign K12[30] = decrypt_int ? K[42] : K[23]; +assign K12[31] = decrypt_int ? K[8] : K[44]; +assign K12[32] = decrypt_int ? K[23] : K[28]; +assign K12[33] = decrypt_int ? K[14] : K[50]; +assign K12[34] = decrypt_int ? K[31] : K[8]; +assign K12[35] = decrypt_int ? K[29] : K[38]; +assign K12[36] = decrypt_int ? K[52] : K[29]; +assign K12[37] = decrypt_int ? K[51] : K[1]; +assign K12[38] = decrypt_int ? K[0] : K[36]; +assign K12[39] = decrypt_int ? K[16] : K[21]; +assign K12[40] = decrypt_int ? K[49] : K[30]; +assign K12[41] = decrypt_int ? K[36] : K[45]; +assign K12[42] = decrypt_int ? K[28] : K[9]; +assign K12[43] = decrypt_int ? K[38] : K[15]; +assign K12[44] = decrypt_int ? K[37] : K[42]; +assign K12[45] = decrypt_int ? K[7] : K[43]; +assign K12[46] = decrypt_int ? K[50] : K[0]; +assign K12[47] = decrypt_int ? K[1] : K[37]; +assign K12[48] = decrypt_int ? K[22] : K[31]; + +assign K11[1] = decrypt_int ? K[53] : K[34]; +assign K11[2] = decrypt_int ? K[17] : K[55]; +assign K11[3] = decrypt_int ? K[32] : K[13]; +assign K11[4] = decrypt_int ? K[41] : K[47]; +assign K11[5] = decrypt_int ? K[19] : K[25]; +assign K11[6] = decrypt_int ? K[47] : K[53]; +assign K11[7] = decrypt_int ? K[33] : K[39]; +assign K11[8] = decrypt_int ? K[12] : K[18]; +assign K11[9] = decrypt_int ? K[3] : K[41]; +assign K11[10] = decrypt_int ? K[54] : K[3]; +assign K11[11] = decrypt_int ? K[20] : K[26]; +assign K11[12] = decrypt_int ? K[25] : K[6]; +assign K11[13] = decrypt_int ? K[34] : K[40]; +assign K11[14] = decrypt_int ? K[6] : K[12]; +assign K11[15] = decrypt_int ? K[39] : K[20]; +assign K11[16] = decrypt_int ? K[40] : K[46]; +assign K11[17] = decrypt_int ? K[55] : K[4]; +assign K11[18] = decrypt_int ? K[11] : K[17]; +assign K11[19] = decrypt_int ? K[10] : K[48]; +assign K11[20] = decrypt_int ? K[4] : K[10]; +assign K11[21] = decrypt_int ? K[5] : K[11]; +assign K11[22] = decrypt_int ? K[13] : K[19]; +assign K11[23] = decrypt_int ? K[46] : K[27]; +assign K11[24] = decrypt_int ? K[26] : K[32]; +assign K11[25] = decrypt_int ? K[44] : K[21]; +assign K11[26] = decrypt_int ? K[35] : K[43]; +assign K11[27] = decrypt_int ? K[29] : K[37]; +assign K11[28] = decrypt_int ? K[16] : K[52]; +assign K11[29] = decrypt_int ? K[0] : K[8]; +assign K11[30] = decrypt_int ? K[1] : K[9]; +assign K11[31] = decrypt_int ? K[22] : K[30]; +assign K11[32] = decrypt_int ? K[37] : K[14]; +assign K11[33] = decrypt_int ? K[28] : K[36]; +assign K11[34] = decrypt_int ? K[45] : K[49]; +assign K11[35] = decrypt_int ? K[43] : K[51]; +assign K11[36] = decrypt_int ? K[7] : K[15]; +assign K11[37] = decrypt_int ? K[38] : K[42]; +assign K11[38] = decrypt_int ? K[14] : K[22]; +assign K11[39] = decrypt_int ? K[30] : K[7]; +assign K11[40] = decrypt_int ? K[8] : K[16]; +assign K11[41] = decrypt_int ? K[50] : K[31]; +assign K11[42] = decrypt_int ? K[42] : K[50]; +assign K11[43] = decrypt_int ? K[52] : K[1]; +assign K11[44] = decrypt_int ? K[51] : K[28]; +assign K11[45] = decrypt_int ? K[21] : K[29]; +assign K11[46] = decrypt_int ? K[9] : K[45]; +assign K11[47] = decrypt_int ? K[15] : K[23]; +assign K11[48] = decrypt_int ? K[36] : K[44]; + +assign K10[1] = decrypt_int ? K[10] : K[20]; +assign K10[2] = decrypt_int ? K[6] : K[41]; +assign K10[3] = decrypt_int ? K[46] : K[24]; +assign K10[4] = decrypt_int ? K[55] : K[33]; +assign K10[5] = decrypt_int ? K[33] : K[11]; +assign K10[6] = decrypt_int ? K[4] : K[39]; +assign K10[7] = decrypt_int ? K[47] : K[25]; +assign K10[8] = decrypt_int ? K[26] : K[4]; +assign K10[9] = decrypt_int ? K[17] : K[27]; +assign K10[10] = decrypt_int ? K[11] : K[46]; +assign K10[11] = decrypt_int ? K[34] : K[12]; +assign K10[12] = decrypt_int ? K[39] : K[17]; +assign K10[13] = decrypt_int ? K[48] : K[26]; +assign K10[14] = decrypt_int ? K[20] : K[55]; +assign K10[15] = decrypt_int ? K[53] : K[6]; +assign K10[16] = decrypt_int ? K[54] : K[32]; +assign K10[17] = decrypt_int ? K[12] : K[47]; +assign K10[18] = decrypt_int ? K[25] : K[3]; +assign K10[19] = decrypt_int ? K[24] : K[34]; +assign K10[20] = decrypt_int ? K[18] : K[53]; +assign K10[21] = decrypt_int ? K[19] : K[54]; +assign K10[22] = decrypt_int ? K[27] : K[5]; +assign K10[23] = decrypt_int ? K[3] : K[13]; +assign K10[24] = decrypt_int ? K[40] : K[18]; +assign K10[25] = decrypt_int ? K[31] : K[7]; +assign K10[26] = decrypt_int ? K[49] : K[29]; +assign K10[27] = decrypt_int ? K[43] : K[23]; +assign K10[28] = decrypt_int ? K[30] : K[38]; +assign K10[29] = decrypt_int ? K[14] : K[49]; +assign K10[30] = decrypt_int ? K[15] : K[50]; +assign K10[31] = decrypt_int ? K[36] : K[16]; +assign K10[32] = decrypt_int ? K[51] : K[0]; +assign K10[33] = decrypt_int ? K[42] : K[22]; +assign K10[34] = decrypt_int ? K[0] : K[35]; +assign K10[35] = decrypt_int ? K[2] : K[37]; +assign K10[36] = decrypt_int ? K[21] : K[1]; +assign K10[37] = decrypt_int ? K[52] : K[28]; +assign K10[38] = decrypt_int ? K[28] : K[8]; +assign K10[39] = decrypt_int ? K[44] : K[52]; +assign K10[40] = decrypt_int ? K[22] : K[2]; +assign K10[41] = decrypt_int ? K[9] : K[44]; +assign K10[42] = decrypt_int ? K[1] : K[36]; +assign K10[43] = decrypt_int ? K[7] : K[42]; +assign K10[44] = decrypt_int ? K[38] : K[14]; +assign K10[45] = decrypt_int ? K[35] : K[15]; +assign K10[46] = decrypt_int ? K[23] : K[31]; +assign K10[47] = decrypt_int ? K[29] : K[9]; +assign K10[48] = decrypt_int ? K[50] : K[30]; + +assign K9[1] = decrypt_int ? K[24] : K[6]; +assign K9[2] = decrypt_int ? K[20] : K[27]; +assign K9[3] = decrypt_int ? K[3] : K[10]; +assign K9[4] = decrypt_int ? K[12] : K[19]; +assign K9[5] = decrypt_int ? K[47] : K[54]; +assign K9[6] = decrypt_int ? K[18] : K[25]; +assign K9[7] = decrypt_int ? K[4] : K[11]; +assign K9[8] = decrypt_int ? K[40] : K[47]; +assign K9[9] = decrypt_int ? K[6] : K[13]; +assign K9[10] = decrypt_int ? K[25] : K[32]; +assign K9[11] = decrypt_int ? K[48] : K[55]; +assign K9[12] = decrypt_int ? K[53] : K[3]; +assign K9[13] = decrypt_int ? K[5] : K[12]; +assign K9[14] = decrypt_int ? K[34] : K[41]; +assign K9[15] = decrypt_int ? K[10] : K[17]; +assign K9[16] = decrypt_int ? K[11] : K[18]; +assign K9[17] = decrypt_int ? K[26] : K[33]; +assign K9[18] = decrypt_int ? K[39] : K[46]; +assign K9[19] = decrypt_int ? K[13] : K[20]; +assign K9[20] = decrypt_int ? K[32] : K[39]; +assign K9[21] = decrypt_int ? K[33] : K[40]; +assign K9[22] = decrypt_int ? K[41] : K[48]; +assign K9[23] = decrypt_int ? K[17] : K[24]; +assign K9[24] = decrypt_int ? K[54] : K[4]; +assign K9[25] = decrypt_int ? K[45] : K[52]; +assign K9[26] = decrypt_int ? K[8] : K[15]; +assign K9[27] = decrypt_int ? K[2] : K[9]; +assign K9[28] = decrypt_int ? K[44] : K[51]; +assign K9[29] = decrypt_int ? K[28] : K[35]; +assign K9[30] = decrypt_int ? K[29] : K[36]; +assign K9[31] = decrypt_int ? K[50] : K[2]; +assign K9[32] = decrypt_int ? K[38] : K[45]; +assign K9[33] = decrypt_int ? K[1] : K[8]; +assign K9[34] = decrypt_int ? K[14] : K[21]; +assign K9[35] = decrypt_int ? K[16] : K[23]; +assign K9[36] = decrypt_int ? K[35] : K[42]; +assign K9[37] = decrypt_int ? K[7] : K[14]; +assign K9[38] = decrypt_int ? K[42] : K[49]; +assign K9[39] = decrypt_int ? K[31] : K[38]; +assign K9[40] = decrypt_int ? K[36] : K[43]; +assign K9[41] = decrypt_int ? K[23] : K[30]; +assign K9[42] = decrypt_int ? K[15] : K[22]; +assign K9[43] = decrypt_int ? K[21] : K[28]; +assign K9[44] = decrypt_int ? K[52] : K[0]; +assign K9[45] = decrypt_int ? K[49] : K[1]; +assign K9[46] = decrypt_int ? K[37] : K[44]; +assign K9[47] = decrypt_int ? K[43] : K[50]; +assign K9[48] = decrypt_int ? K[9] : K[16]; + +assign K8[1] = decrypt_int ? K[6] : K[24]; +assign K8[2] = decrypt_int ? K[27] : K[20]; +assign K8[3] = decrypt_int ? K[10] : K[3]; +assign K8[4] = decrypt_int ? K[19] : K[12]; +assign K8[5] = decrypt_int ? K[54] : K[47]; +assign K8[6] = decrypt_int ? K[25] : K[18]; +assign K8[7] = decrypt_int ? K[11] : K[4]; +assign K8[8] = decrypt_int ? K[47] : K[40]; +assign K8[9] = decrypt_int ? K[13] : K[6]; +assign K8[10] = decrypt_int ? K[32] : K[25]; +assign K8[11] = decrypt_int ? K[55] : K[48]; +assign K8[12] = decrypt_int ? K[3] : K[53]; +assign K8[13] = decrypt_int ? K[12] : K[5]; +assign K8[14] = decrypt_int ? K[41] : K[34]; +assign K8[15] = decrypt_int ? K[17] : K[10]; +assign K8[16] = decrypt_int ? K[18] : K[11]; +assign K8[17] = decrypt_int ? K[33] : K[26]; +assign K8[18] = decrypt_int ? K[46] : K[39]; +assign K8[19] = decrypt_int ? K[20] : K[13]; +assign K8[20] = decrypt_int ? K[39] : K[32]; +assign K8[21] = decrypt_int ? K[40] : K[33]; +assign K8[22] = decrypt_int ? K[48] : K[41]; +assign K8[23] = decrypt_int ? K[24] : K[17]; +assign K8[24] = decrypt_int ? K[4] : K[54]; +assign K8[25] = decrypt_int ? K[52] : K[45]; +assign K8[26] = decrypt_int ? K[15] : K[8]; +assign K8[27] = decrypt_int ? K[9] : K[2]; +assign K8[28] = decrypt_int ? K[51] : K[44]; +assign K8[29] = decrypt_int ? K[35] : K[28]; +assign K8[30] = decrypt_int ? K[36] : K[29]; +assign K8[31] = decrypt_int ? K[2] : K[50]; +assign K8[32] = decrypt_int ? K[45] : K[38]; +assign K8[33] = decrypt_int ? K[8] : K[1]; +assign K8[34] = decrypt_int ? K[21] : K[14]; +assign K8[35] = decrypt_int ? K[23] : K[16]; +assign K8[36] = decrypt_int ? K[42] : K[35]; +assign K8[37] = decrypt_int ? K[14] : K[7]; +assign K8[38] = decrypt_int ? K[49] : K[42]; +assign K8[39] = decrypt_int ? K[38] : K[31]; +assign K8[40] = decrypt_int ? K[43] : K[36]; +assign K8[41] = decrypt_int ? K[30] : K[23]; +assign K8[42] = decrypt_int ? K[22] : K[15]; +assign K8[43] = decrypt_int ? K[28] : K[21]; +assign K8[44] = decrypt_int ? K[0] : K[52]; +assign K8[45] = decrypt_int ? K[1] : K[49]; +assign K8[46] = decrypt_int ? K[44] : K[37]; +assign K8[47] = decrypt_int ? K[50] : K[43]; +assign K8[48] = decrypt_int ? K[16] : K[9]; + +assign K7[1] = decrypt_int ? K[20] : K[10]; +assign K7[2] = decrypt_int ? K[41] : K[6]; +assign K7[3] = decrypt_int ? K[24] : K[46]; +assign K7[4] = decrypt_int ? K[33] : K[55]; +assign K7[5] = decrypt_int ? K[11] : K[33]; +assign K7[6] = decrypt_int ? K[39] : K[4]; +assign K7[7] = decrypt_int ? K[25] : K[47]; +assign K7[8] = decrypt_int ? K[4] : K[26]; +assign K7[9] = decrypt_int ? K[27] : K[17]; +assign K7[10] = decrypt_int ? K[46] : K[11]; +assign K7[11] = decrypt_int ? K[12] : K[34]; +assign K7[12] = decrypt_int ? K[17] : K[39]; +assign K7[13] = decrypt_int ? K[26] : K[48]; +assign K7[14] = decrypt_int ? K[55] : K[20]; +assign K7[15] = decrypt_int ? K[6] : K[53]; +assign K7[16] = decrypt_int ? K[32] : K[54]; +assign K7[17] = decrypt_int ? K[47] : K[12]; +assign K7[18] = decrypt_int ? K[3] : K[25]; +assign K7[19] = decrypt_int ? K[34] : K[24]; +assign K7[20] = decrypt_int ? K[53] : K[18]; +assign K7[21] = decrypt_int ? K[54] : K[19]; +assign K7[22] = decrypt_int ? K[5] : K[27]; +assign K7[23] = decrypt_int ? K[13] : K[3]; +assign K7[24] = decrypt_int ? K[18] : K[40]; +assign K7[25] = decrypt_int ? K[7] : K[31]; +assign K7[26] = decrypt_int ? K[29] : K[49]; +assign K7[27] = decrypt_int ? K[23] : K[43]; +assign K7[28] = decrypt_int ? K[38] : K[30]; +assign K7[29] = decrypt_int ? K[49] : K[14]; +assign K7[30] = decrypt_int ? K[50] : K[15]; +assign K7[31] = decrypt_int ? K[16] : K[36]; +assign K7[32] = decrypt_int ? K[0] : K[51]; +assign K7[33] = decrypt_int ? K[22] : K[42]; +assign K7[34] = decrypt_int ? K[35] : K[0]; +assign K7[35] = decrypt_int ? K[37] : K[2]; +assign K7[36] = decrypt_int ? K[1] : K[21]; +assign K7[37] = decrypt_int ? K[28] : K[52]; +assign K7[38] = decrypt_int ? K[8] : K[28]; +assign K7[39] = decrypt_int ? K[52] : K[44]; +assign K7[40] = decrypt_int ? K[2] : K[22]; +assign K7[41] = decrypt_int ? K[44] : K[9]; +assign K7[42] = decrypt_int ? K[36] : K[1]; +assign K7[43] = decrypt_int ? K[42] : K[7]; +assign K7[44] = decrypt_int ? K[14] : K[38]; +assign K7[45] = decrypt_int ? K[15] : K[35]; +assign K7[46] = decrypt_int ? K[31] : K[23]; +assign K7[47] = decrypt_int ? K[9] : K[29]; +assign K7[48] = decrypt_int ? K[30] : K[50]; + +assign K6[1] = decrypt_int ? K[34] : K[53]; +assign K6[2] = decrypt_int ? K[55] : K[17]; +assign K6[3] = decrypt_int ? K[13] : K[32]; +assign K6[4] = decrypt_int ? K[47] : K[41]; +assign K6[5] = decrypt_int ? K[25] : K[19]; +assign K6[6] = decrypt_int ? K[53] : K[47]; +assign K6[7] = decrypt_int ? K[39] : K[33]; +assign K6[8] = decrypt_int ? K[18] : K[12]; +assign K6[9] = decrypt_int ? K[41] : K[3]; +assign K6[10] = decrypt_int ? K[3] : K[54]; +assign K6[11] = decrypt_int ? K[26] : K[20]; +assign K6[12] = decrypt_int ? K[6] : K[25]; +assign K6[13] = decrypt_int ? K[40] : K[34]; +assign K6[14] = decrypt_int ? K[12] : K[6]; +assign K6[15] = decrypt_int ? K[20] : K[39]; +assign K6[16] = decrypt_int ? K[46] : K[40]; +assign K6[17] = decrypt_int ? K[4] : K[55]; +assign K6[18] = decrypt_int ? K[17] : K[11]; +assign K6[19] = decrypt_int ? K[48] : K[10]; +assign K6[20] = decrypt_int ? K[10] : K[4]; +assign K6[21] = decrypt_int ? K[11] : K[5]; +assign K6[22] = decrypt_int ? K[19] : K[13]; +assign K6[23] = decrypt_int ? K[27] : K[46]; +assign K6[24] = decrypt_int ? K[32] : K[26]; +assign K6[25] = decrypt_int ? K[21] : K[44]; +assign K6[26] = decrypt_int ? K[43] : K[35]; +assign K6[27] = decrypt_int ? K[37] : K[29]; +assign K6[28] = decrypt_int ? K[52] : K[16]; +assign K6[29] = decrypt_int ? K[8] : K[0]; +assign K6[30] = decrypt_int ? K[9] : K[1]; +assign K6[31] = decrypt_int ? K[30] : K[22]; +assign K6[32] = decrypt_int ? K[14] : K[37]; +assign K6[33] = decrypt_int ? K[36] : K[28]; +assign K6[34] = decrypt_int ? K[49] : K[45]; +assign K6[35] = decrypt_int ? K[51] : K[43]; +assign K6[36] = decrypt_int ? K[15] : K[7]; +assign K6[37] = decrypt_int ? K[42] : K[38]; +assign K6[38] = decrypt_int ? K[22] : K[14]; +assign K6[39] = decrypt_int ? K[7] : K[30]; +assign K6[40] = decrypt_int ? K[16] : K[8]; +assign K6[41] = decrypt_int ? K[31] : K[50]; +assign K6[42] = decrypt_int ? K[50] : K[42]; +assign K6[43] = decrypt_int ? K[1] : K[52]; +assign K6[44] = decrypt_int ? K[28] : K[51]; +assign K6[45] = decrypt_int ? K[29] : K[21]; +assign K6[46] = decrypt_int ? K[45] : K[9]; +assign K6[47] = decrypt_int ? K[23] : K[15]; +assign K6[48] = decrypt_int ? K[44] : K[36]; + +assign K5[1] = decrypt_int ? K[48] : K[39]; +assign K5[2] = decrypt_int ? K[12] : K[3]; +assign K5[3] = decrypt_int ? K[27] : K[18]; +assign K5[4] = decrypt_int ? K[4] : K[27]; +assign K5[5] = decrypt_int ? K[39] : K[5]; +assign K5[6] = decrypt_int ? K[10] : K[33]; +assign K5[7] = decrypt_int ? K[53] : K[19]; +assign K5[8] = decrypt_int ? K[32] : K[55]; +assign K5[9] = decrypt_int ? K[55] : K[46]; +assign K5[10] = decrypt_int ? K[17] : K[40]; +assign K5[11] = decrypt_int ? K[40] : K[6]; +assign K5[12] = decrypt_int ? K[20] : K[11]; +assign K5[13] = decrypt_int ? K[54] : K[20]; +assign K5[14] = decrypt_int ? K[26] : K[17]; +assign K5[15] = decrypt_int ? K[34] : K[25]; +assign K5[16] = decrypt_int ? K[3] : K[26]; +assign K5[17] = decrypt_int ? K[18] : K[41]; +assign K5[18] = decrypt_int ? K[6] : K[54]; +assign K5[19] = decrypt_int ? K[5] : K[53]; +assign K5[20] = decrypt_int ? K[24] : K[47]; +assign K5[21] = decrypt_int ? K[25] : K[48]; +assign K5[22] = decrypt_int ? K[33] : K[24]; +assign K5[23] = decrypt_int ? K[41] : K[32]; +assign K5[24] = decrypt_int ? K[46] : K[12]; +assign K5[25] = decrypt_int ? K[35] : K[30]; +assign K5[26] = decrypt_int ? K[2] : K[21]; +assign K5[27] = decrypt_int ? K[51] : K[15]; +assign K5[28] = decrypt_int ? K[7] : K[2]; +assign K5[29] = decrypt_int ? K[22] : K[45]; +assign K5[30] = decrypt_int ? K[23] : K[42]; +assign K5[31] = decrypt_int ? K[44] : K[8]; +assign K5[32] = decrypt_int ? K[28] : K[23]; +assign K5[33] = decrypt_int ? K[50] : K[14]; +assign K5[34] = decrypt_int ? K[8] : K[31]; +assign K5[35] = decrypt_int ? K[38] : K[29]; +assign K5[36] = decrypt_int ? K[29] : K[52]; +assign K5[37] = decrypt_int ? K[1] : K[51]; +assign K5[38] = decrypt_int ? K[36] : K[0]; +assign K5[39] = decrypt_int ? K[21] : K[16]; +assign K5[40] = decrypt_int ? K[30] : K[49]; +assign K5[41] = decrypt_int ? K[45] : K[36]; +assign K5[42] = decrypt_int ? K[9] : K[28]; +assign K5[43] = decrypt_int ? K[15] : K[38]; +assign K5[44] = decrypt_int ? K[42] : K[37]; +assign K5[45] = decrypt_int ? K[43] : K[7]; +assign K5[46] = decrypt_int ? K[0] : K[50]; +assign K5[47] = decrypt_int ? K[37] : K[1]; +assign K5[48] = decrypt_int ? K[31] : K[22]; + +assign K4[1] = decrypt_int ? K[5] : K[25]; +assign K4[2] = decrypt_int ? K[26] : K[46]; +assign K4[3] = decrypt_int ? K[41] : K[4]; +assign K4[4] = decrypt_int ? K[18] : K[13]; +assign K4[5] = decrypt_int ? K[53] : K[48]; +assign K4[6] = decrypt_int ? K[24] : K[19]; +assign K4[7] = decrypt_int ? K[10] : K[5]; +assign K4[8] = decrypt_int ? K[46] : K[41]; +assign K4[9] = decrypt_int ? K[12] : K[32]; +assign K4[10] = decrypt_int ? K[6] : K[26]; +assign K4[11] = decrypt_int ? K[54] : K[17]; +assign K4[12] = decrypt_int ? K[34] : K[54]; +assign K4[13] = decrypt_int ? K[11] : K[6]; +assign K4[14] = decrypt_int ? K[40] : K[3]; +assign K4[15] = decrypt_int ? K[48] : K[11]; +assign K4[16] = decrypt_int ? K[17] : K[12]; +assign K4[17] = decrypt_int ? K[32] : K[27]; +assign K4[18] = decrypt_int ? K[20] : K[40]; +assign K4[19] = decrypt_int ? K[19] : K[39]; +assign K4[20] = decrypt_int ? K[13] : K[33]; +assign K4[21] = decrypt_int ? K[39] : K[34]; +assign K4[22] = decrypt_int ? K[47] : K[10]; +assign K4[23] = decrypt_int ? K[55] : K[18]; +assign K4[24] = decrypt_int ? K[3] : K[55]; +assign K4[25] = decrypt_int ? K[49] : K[16]; +assign K4[26] = decrypt_int ? K[16] : K[7]; +assign K4[27] = decrypt_int ? K[38] : K[1]; +assign K4[28] = decrypt_int ? K[21] : K[43]; +assign K4[29] = decrypt_int ? K[36] : K[31]; +assign K4[30] = decrypt_int ? K[37] : K[28]; +assign K4[31] = decrypt_int ? K[31] : K[49]; +assign K4[32] = decrypt_int ? K[42] : K[9]; +assign K4[33] = decrypt_int ? K[9] : K[0]; +assign K4[34] = decrypt_int ? K[22] : K[44]; +assign K4[35] = decrypt_int ? K[52] : K[15]; +assign K4[36] = decrypt_int ? K[43] : K[38]; +assign K4[37] = decrypt_int ? K[15] : K[37]; +assign K4[38] = decrypt_int ? K[50] : K[45]; +assign K4[39] = decrypt_int ? K[35] : K[2]; +assign K4[40] = decrypt_int ? K[44] : K[35]; +assign K4[41] = decrypt_int ? K[0] : K[22]; +assign K4[42] = decrypt_int ? K[23] : K[14]; +assign K4[43] = decrypt_int ? K[29] : K[51]; +assign K4[44] = decrypt_int ? K[1] : K[23]; +assign K4[45] = decrypt_int ? K[2] : K[52]; +assign K4[46] = decrypt_int ? K[14] : K[36]; +assign K4[47] = decrypt_int ? K[51] : K[42]; +assign K4[48] = decrypt_int ? K[45] : K[8]; + +assign K3[1] = decrypt_int ? K[19] : K[11]; +assign K3[2] = decrypt_int ? K[40] : K[32]; +assign K3[3] = decrypt_int ? K[55] : K[47]; +assign K3[4] = decrypt_int ? K[32] : K[24]; +assign K3[5] = decrypt_int ? K[10] : K[34]; +assign K3[6] = decrypt_int ? K[13] : K[5]; +assign K3[7] = decrypt_int ? K[24] : K[48]; +assign K3[8] = decrypt_int ? K[3] : K[27]; +assign K3[9] = decrypt_int ? K[26] : K[18]; +assign K3[10] = decrypt_int ? K[20] : K[12]; +assign K3[11] = decrypt_int ? K[11] : K[3]; +assign K3[12] = decrypt_int ? K[48] : K[40]; +assign K3[13] = decrypt_int ? K[25] : K[17]; +assign K3[14] = decrypt_int ? K[54] : K[46]; +assign K3[15] = decrypt_int ? K[5] : K[54]; +assign K3[16] = decrypt_int ? K[6] : K[55]; +assign K3[17] = decrypt_int ? K[46] : K[13]; +assign K3[18] = decrypt_int ? K[34] : K[26]; +assign K3[19] = decrypt_int ? K[33] : K[25]; +assign K3[20] = decrypt_int ? K[27] : K[19]; +assign K3[21] = decrypt_int ? K[53] : K[20]; +assign K3[22] = decrypt_int ? K[4] : K[53]; +assign K3[23] = decrypt_int ? K[12] : K[4]; +assign K3[24] = decrypt_int ? K[17] : K[41]; +assign K3[25] = decrypt_int ? K[8] : K[2]; +assign K3[26] = decrypt_int ? K[30] : K[52]; +assign K3[27] = decrypt_int ? K[52] : K[42]; +assign K3[28] = decrypt_int ? K[35] : K[29]; +assign K3[29] = decrypt_int ? K[50] : K[44]; +assign K3[30] = decrypt_int ? K[51] : K[14]; +assign K3[31] = decrypt_int ? K[45] : K[35]; +assign K3[32] = decrypt_int ? K[1] : K[50]; +assign K3[33] = decrypt_int ? K[23] : K[45]; +assign K3[34] = decrypt_int ? K[36] : K[30]; +assign K3[35] = decrypt_int ? K[7] : K[1]; +assign K3[36] = decrypt_int ? K[2] : K[51]; +assign K3[37] = decrypt_int ? K[29] : K[23]; +assign K3[38] = decrypt_int ? K[9] : K[31]; +assign K3[39] = decrypt_int ? K[49] : K[43]; +assign K3[40] = decrypt_int ? K[31] : K[21]; +assign K3[41] = decrypt_int ? K[14] : K[8]; +assign K3[42] = decrypt_int ? K[37] : K[0]; +assign K3[43] = decrypt_int ? K[43] : K[37]; +assign K3[44] = decrypt_int ? K[15] : K[9]; +assign K3[45] = decrypt_int ? K[16] : K[38]; +assign K3[46] = decrypt_int ? K[28] : K[22]; +assign K3[47] = decrypt_int ? K[38] : K[28]; +assign K3[48] = decrypt_int ? K[0] : K[49]; + +assign K2[1] = decrypt_int ? K[33] : K[54]; +assign K2[2] = decrypt_int ? K[54] : K[18]; +assign K2[3] = decrypt_int ? K[12] : K[33]; +assign K2[4] = decrypt_int ? K[46] : K[10]; +assign K2[5] = decrypt_int ? K[24] : K[20]; +assign K2[6] = decrypt_int ? K[27] : K[48]; +assign K2[7] = decrypt_int ? K[13] : K[34]; +assign K2[8] = decrypt_int ? K[17] : K[13]; +assign K2[9] = decrypt_int ? K[40] : K[4]; +assign K2[10] = decrypt_int ? K[34] : K[55]; +assign K2[11] = decrypt_int ? K[25] : K[46]; +assign K2[12] = decrypt_int ? K[5] : K[26]; +assign K2[13] = decrypt_int ? K[39] : K[3]; +assign K2[14] = decrypt_int ? K[11] : K[32]; +assign K2[15] = decrypt_int ? K[19] : K[40]; +assign K2[16] = decrypt_int ? K[20] : K[41]; +assign K2[17] = decrypt_int ? K[3] : K[24]; +assign K2[18] = decrypt_int ? K[48] : K[12]; +assign K2[19] = decrypt_int ? K[47] : K[11]; +assign K2[20] = decrypt_int ? K[41] : K[5]; +assign K2[21] = decrypt_int ? K[10] : K[6]; +assign K2[22] = decrypt_int ? K[18] : K[39]; +assign K2[23] = decrypt_int ? K[26] : K[47]; +assign K2[24] = decrypt_int ? K[6] : K[27]; +assign K2[25] = decrypt_int ? K[22] : K[43]; +assign K2[26] = decrypt_int ? K[44] : K[38]; +assign K2[27] = decrypt_int ? K[7] : K[28]; +assign K2[28] = decrypt_int ? K[49] : K[15]; +assign K2[29] = decrypt_int ? K[9] : K[30]; +assign K2[30] = decrypt_int ? K[38] : K[0]; +assign K2[31] = decrypt_int ? K[0] : K[21]; +assign K2[32] = decrypt_int ? K[15] : K[36]; +assign K2[33] = decrypt_int ? K[37] : K[31]; +assign K2[34] = decrypt_int ? K[50] : K[16]; +assign K2[35] = decrypt_int ? K[21] : K[42]; +assign K2[36] = decrypt_int ? K[16] : K[37]; +assign K2[37] = decrypt_int ? K[43] : K[9]; +assign K2[38] = decrypt_int ? K[23] : K[44]; +assign K2[39] = decrypt_int ? K[8] : K[29]; +assign K2[40] = decrypt_int ? K[45] : K[7]; +assign K2[41] = decrypt_int ? K[28] : K[49]; +assign K2[42] = decrypt_int ? K[51] : K[45]; +assign K2[43] = decrypt_int ? K[2] : K[23]; +assign K2[44] = decrypt_int ? K[29] : K[50]; +assign K2[45] = decrypt_int ? K[30] : K[51]; +assign K2[46] = decrypt_int ? K[42] : K[8]; +assign K2[47] = decrypt_int ? K[52] : K[14]; +assign K2[48] = decrypt_int ? K[14] : K[35]; + +assign K1[1] = decrypt_int ? K[40] : K[47]; +assign K1[2] = decrypt_int ? K[4] : K[11]; +assign K1[3] = decrypt_int ? K[19] : K[26]; +assign K1[4] = decrypt_int ? K[53] : K[3]; +assign K1[5] = decrypt_int ? K[6] : K[13]; +assign K1[6] = decrypt_int ? K[34] : K[41]; +assign K1[7] = decrypt_int ? K[20] : K[27]; +assign K1[8] = decrypt_int ? K[24] : K[6]; +assign K1[9] = decrypt_int ? K[47] : K[54]; +assign K1[10] = decrypt_int ? K[41] : K[48]; +assign K1[11] = decrypt_int ? K[32] : K[39]; +assign K1[12] = decrypt_int ? K[12] : K[19]; +assign K1[13] = decrypt_int ? K[46] : K[53]; +assign K1[14] = decrypt_int ? K[18] : K[25]; +assign K1[15] = decrypt_int ? K[26] : K[33]; +assign K1[16] = decrypt_int ? K[27] : K[34]; +assign K1[17] = decrypt_int ? K[10] : K[17]; +assign K1[18] = decrypt_int ? K[55] : K[5]; +assign K1[19] = decrypt_int ? K[54] : K[4]; +assign K1[20] = decrypt_int ? K[48] : K[55]; +assign K1[21] = decrypt_int ? K[17] : K[24]; +assign K1[22] = decrypt_int ? K[25] : K[32]; +assign K1[23] = decrypt_int ? K[33] : K[40]; +assign K1[24] = decrypt_int ? K[13] : K[20]; +assign K1[25] = decrypt_int ? K[29] : K[36]; +assign K1[26] = decrypt_int ? K[51] : K[31]; +assign K1[27] = decrypt_int ? K[14] : K[21]; +assign K1[28] = decrypt_int ? K[1] : K[8]; +assign K1[29] = decrypt_int ? K[16] : K[23]; +assign K1[30] = decrypt_int ? K[45] : K[52]; +assign K1[31] = decrypt_int ? K[7] : K[14]; +assign K1[32] = decrypt_int ? K[22] : K[29]; +assign K1[33] = decrypt_int ? K[44] : K[51]; +assign K1[34] = decrypt_int ? K[2] : K[9]; +assign K1[35] = decrypt_int ? K[28] : K[35]; +assign K1[36] = decrypt_int ? K[23] : K[30]; +assign K1[37] = decrypt_int ? K[50] : K[2]; +assign K1[38] = decrypt_int ? K[30] : K[37]; +assign K1[39] = decrypt_int ? K[15] : K[22]; +assign K1[40] = decrypt_int ? K[52] : K[0]; +assign K1[41] = decrypt_int ? K[35] : K[42]; +assign K1[42] = decrypt_int ? K[31] : K[38]; +assign K1[43] = decrypt_int ? K[9] : K[16]; +assign K1[44] = decrypt_int ? K[36] : K[43]; +assign K1[45] = decrypt_int ? K[37] : K[44]; +assign K1[46] = decrypt_int ? K[49] : K[1]; +assign K1[47] = decrypt_int ? K[0] : K[7]; +assign K1[48] = decrypt_int ? K[21] : K[28]; + +endmodule From ff4460695b83374b6a4f7dca811447d4b7462c3e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 17:00:55 -0600 Subject: [PATCH 129/352] [HDL] Add dff tech map files for yosys --- .../openfpga_yosys_techlib/openfpga_dff_map.v | 65 +++++++++++++ .../openfpga_yosys_techlib/openfpga_dff_sim.v | 96 +++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v create mode 100644 openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v new file mode 100644 index 000000000..156e8c3da --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v @@ -0,0 +1,65 @@ +// Basic DFF +module \$_DFF_P_ (D, C, Q); + input D; + input C; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dff _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C)); +endmodule + +// Async reset +module \$_DFF_PP0_ (D, C, R, Q); + input D; + input C; + input R; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dffr _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .R(R)); +endmodule + +// Async reset, enable +module \$_DFFE_PP0P_ (D, C, E, R, Q); + input D; + input C; + input E; + input R; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dffre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); +endmodule + +// Latch with Async reset, enable +module \$_DLATCH_PP0_ (input E, R, D, output Q); + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + latchre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(R)); +endmodule + +// The following techmap operation are not performed right now +// as Negative edge FF are not legalized in synth_quicklogic for qlf_k6n10 +// but in case we implement clock inversion in the future, the support is ready for it. +module \$_DFF_N_ (D, C, Q); + input D; + input C; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dff #(.IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C)); +endmodule + +module \$_DFF_NP0_ (D, C, R, Q); + input D; + input C; + input R; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dffr #(.IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .R(R)); +endmodule + +module \$_DFFE_NP0P_ (D, C, E, R, Q); + input D; + input C; + input E; + input R; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dffre #(.IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); +endmodule \ No newline at end of file diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v new file mode 100644 index 000000000..90926cef6 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v @@ -0,0 +1,96 @@ +(* abc9_flop, lib_whitebox *) +module dff( + output reg Q, + input D, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C +); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + initial Q = INIT; + case(|IS_C_INVERTED) + 1'b0: + always @(posedge C) + Q <= D; + 1'b1: + always @(negedge C) + Q <= D; + endcase +endmodule + +(* abc9_flop, lib_whitebox *) +module dffr( + output reg Q, + input D, + input R, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C +); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + initial Q = INIT; + case(|IS_C_INVERTED) + 1'b0: + always @(posedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else + Q <= D; + 1'b1: + always @(negedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else + Q <= D; + endcase +endmodule + +(* abc9_flop, lib_whitebox *) +module dffre( + output reg Q, + input D, + input R, + input E, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C +); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + initial Q = INIT; + case(|IS_C_INVERTED) + 1'b0: + always @(posedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else if(E) + Q <= D; + 1'b1: + always @(negedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else if(E) + Q <= D; + endcase +endmodule + +(* abc9_flop, lib_whitebox *) +module latchre ( + output reg Q, + input S, + input R, + input D, + input G, + input E +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @* + begin + if (R) Q <= 1'b0; + if (S) Q <= 1'b1; + else if (E && G) Q <= D; + end +endmodule \ No newline at end of file From 64294ae4ebae2be875b3eda35791096ef6a9ec1d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 19:25:54 -0600 Subject: [PATCH 130/352] [Doc] Update README for architecture files due to new architecture features --- openfpga_flow/openfpga_arch/README.md | 1 + openfpga_flow/vpr_arch/README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md index 73f412c9c..9ba9073f3 100644 --- a/openfpga_flow/openfpga_arch/README.md +++ b/openfpga_flow/openfpga_arch/README.md @@ -6,6 +6,7 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f * The keyword 'frac' is to specify if fracturable LUT is used or not. * The keyword 'Native' is to specify if fracturable LUT design is a native one (without mode switch) or a standard one (with mode switch). - N: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number. +- fracdff: Use multi-mode DFF model, where reset/set/clock polarity is configurable - adder\_chain: If hard adder/carry chain is used inside CLBs - register\_chain: If shift register chain is used inside CLBs - scan\_chain: If scan chain testing infrastructure is used inside CLBs diff --git a/openfpga_flow/vpr_arch/README.md b/openfpga_flow/vpr_arch/README.md index 9ee9dd0ff..f3862b1ee 100644 --- a/openfpga_flow/vpr_arch/README.md +++ b/openfpga_flow/vpr_arch/README.md @@ -7,6 +7,7 @@ Please reveal the following architecture features in the names to help quickly s - N: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number. - tileable: If the routing architecture is tileable or not. * The keyword 'IO' specifies if the I/O tile is tileable or not +- fracdff: Use multi-mode DFF model, where reset/set/clock polarity is configurable - adder\_chain: If hard adder/carry chain is used inside CLBs - register\_chain: If shift register chain is used inside CLBs - scan\_chain: If scan chain testing infrastructure is used inside CLBs From f2f7f010ea77f065e9f206573930c497b3fec7b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 19:26:18 -0600 Subject: [PATCH 131/352] [Arch] Add new architectures using DFF with reset in VPR --- .../k4_frac_N4_fracff_40nm_cc_openfpga.xml | 239 +++++++++ .../k4_frac_N4_tileable_fracff_40nm.xml | 479 ++++++++++++++++++ ...n_chain_nonLR_caravel_io_skywater130nm.xml | 12 + 3 files changed, 730 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml create mode 100644 openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml diff --git a/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml new file mode 100644 index 000000000..951050bc8 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml new file mode 100644 index 000000000..1b21f5c13 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml index 9586e984c..4f6db9394 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml @@ -43,6 +43,18 @@ + + + + + + + + + + + + From 4239bb4e6809f5d509a01139bf9425faed0618bd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 19:59:55 -0600 Subject: [PATCH 132/352] [Arch] Patch architecture files using multi-mode DFFs --- .../k4_frac_N4_fracff_40nm_cc_openfpga.xml | 4 ++-- .../vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml index 951050bc8..7d3ea06b4 100644 --- a/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml @@ -145,9 +145,9 @@ - + - + diff --git a/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml index 1b21f5c13..f9d57e4ca 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml @@ -79,9 +79,13 @@ + - + + + + @@ -278,7 +282,7 @@ - + @@ -344,12 +348,13 @@ - + + @@ -359,7 +364,7 @@ - + @@ -413,7 +418,7 @@ - + @@ -461,6 +466,7 @@ + - - - + + + - + @@ -284,18 +284,18 @@ - + - - - - + + + + - - + + @@ -350,12 +350,12 @@ - + - - - - + + + + @@ -363,8 +363,8 @@ - - + + @@ -420,12 +420,12 @@ - + - - - - + + + + @@ -433,8 +433,8 @@ - - + + From 0a15f366cb018e2de3dfd85f66b23a9542c7b134 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 20:48:15 -0600 Subject: [PATCH 141/352] [HDL] Patch dff models used in yosys tech map --- openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v index 156e8c3da..707d9c0e6 100644 --- a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v @@ -62,4 +62,4 @@ module \$_DFFE_NP0P_ (D, C, E, R, Q); output Q; parameter _TECHMAP_WIREINIT_Q_ = 1'bx; dffre #(.IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); -endmodule \ No newline at end of file +endmodule From 7172fc9ea1c2f115bac7a9930f81074ea0d4469b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 20:48:37 -0600 Subject: [PATCH 142/352] [Test] Patch test for architecture using asynchronous DFFs --- .../k4_series/k4n4_fracff/config/task.conf | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf index 4e271f677..58be5a2bb 100644 --- a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf @@ -9,17 +9,16 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 3*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=2x2 +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml # Yosys script parameters yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v @@ -28,11 +27,13 @@ yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_async_reset/counter.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys -bench0_top = and2 +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = counter [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From e3dafe99dafc08a24553efd5d3a4b9cfa31f4c96 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Apr 2021 20:58:32 -0600 Subject: [PATCH 143/352] [Arch] Revert to old version arch due to editing by mistake --- ...ter_scan_chain_nonLR_caravel_io_skywater130nm.xml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml index 4f6db9394..9586e984c 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_register_scan_chain_nonLR_caravel_io_skywater130nm.xml @@ -43,18 +43,6 @@ - - - - - - - - - - - - From da95da933ba7f55924bdd0f18b57e59eac41473d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 15:04:26 -0600 Subject: [PATCH 144/352] [Test] Add pin constraint file to map reset to correct FPGA pins --- .../k4_series/k4n4_fracff/config/pin_constraints.xml | 7 +++++++ .../basic_tests/k4_series/k4n4_fracff/config/task.conf | 1 + 2 files changed, 8 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml new file mode 100644 index 000000000..abcf209f6 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf index 58be5a2bb..07e326a1e 100644 --- a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf @@ -19,6 +19,7 @@ fpga_flow=yosys_vpr openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_pin_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml # Yosys script parameters yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v From 7018073e28194c684aab5b0e93bcc15960996090 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 15:04:51 -0600 Subject: [PATCH 145/352] [Script] Update openfpga shell script w/o ace usage to adapt pin constraint files --- .../openfpga_shell_scripts/example_without_ace_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index f694b3c03..3c1be9114 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator +write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Write the SDC files for PnR backend # - Turn on every options here From 6e1b58f8a66353c5aba4d2945088711d12cc5022 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 15:05:22 -0600 Subject: [PATCH 146/352] [Tool] Update FPGA-Verilog testbench generator to accept pin constraints to non-clock global ports --- .../verilog_preconfig_top_module.cpp | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 542eadc2e..d55a59834 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -173,8 +173,32 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, } /* For other ports, give an default value */ - std::vector default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); - print_verilog_wire_constant_values(fp, module_global_port, default_values); + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) { + BasicPort module_global_pin(module_global_port.get_name(), + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); + + /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ + std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); + for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { + if (module_global_pin == pin_constraints.pin(pin_constraint)) { + constrained_net_name = pin_constraints.net(pin_constraint); + break; + } + } + + /* - If constrained to a given net in the benchmark, we connect the global pin to the net + * - If constrained to an open net in the benchmark, we assign it to a default value + */ + if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { + BasicPort benchmark_pin(constrained_net_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1); + print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false); + } else { + VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name); + std::vector default_values(module_global_pin.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); + print_verilog_wire_constant_values(fp, module_global_pin, default_values); + } + } } print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----")); From da619fabe7114eadee3c240d29cf8686ac244d52 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 17:19:34 -0600 Subject: [PATCH 147/352] [Tool] FPGA-Verilog testbench generator accepts pin constraints in full testbench --- .../fpga_verilog/verilog_top_testbench.cpp | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 08b7cd2e8..cc7b9fb98 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -264,6 +264,7 @@ static void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, + const PinConstraints& pin_constraints, const FabricGlobalPortInfo& fabric_global_port_info, const SimulationSetting& simulation_parameters, const bool& active_global_prog_reset, @@ -373,18 +374,48 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, stimuli_reset_port.set_name(std::string(TOP_TB_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); } - /* Wire the port to the input stimuli: - * The wiring will be inverted if the default value of the global port is 1 - * Otherwise, the wiring will not be inverted! - */ - if (true == activate) { - print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), - stimuli_reset_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); - } else { - VTR_ASSERT_SAFE(false == activate); - print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port), - std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + + BasicPort module_global_port_info = module_manager.module_port(top_module, module_global_port); + + for (size_t pin_id = 0; pin_id < module_global_port_info.pins().size(); ++pin_id) { + BasicPort module_global_pin(module_global_port_info.get_name(), + module_global_port_info.pins()[pin_id], + module_global_port_info.pins()[pin_id]); + + /* Regular reset port can be mapped by a net from user design */ + if (false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ + std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); + for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { + if (module_global_pin == pin_constraints.pin(pin_constraint)) { + constrained_net_name = pin_constraints.net(pin_constraint); + break; + } + } + + /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ + if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { + BasicPort benchmark_pin(constrained_net_name, 1); + print_verilog_wire_connection(fp, module_global_pin, + benchmark_pin, + false); + continue; /* Finish the net assignment for this reset pin */ + } + } + + /* Wire the port to the input stimuli: + * The wiring will be inverted if the default value of the global port is 1 + * Otherwise, the wiring will not be inverted! + */ + if (true == activate) { + print_verilog_wire_connection(fp, module_global_pin, + stimuli_reset_port, + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + } else { + VTR_ASSERT_SAFE(false == activate); + print_verilog_wire_constant_values(fp, module_global_pin, + std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + } } } @@ -1994,6 +2025,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli(fp, module_manager, top_module, + pin_constraints, global_ports, simulation_parameters, active_global_prog_reset, From d95a1e277695d930f45a64347389a655dd26a568 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 17:31:55 -0600 Subject: [PATCH 148/352] [Tool] Encapulate search function in PinConstraint data structure --- libopenfpga/libpcf/src/pin_constraints.cpp | 11 +++++++++++ libopenfpga/libpcf/src/pin_constraints.h | 5 +++++ .../verilog_preconfig_top_module.cpp | 16 ++-------------- .../src/fpga_verilog/verilog_top_testbench.cpp | 8 +------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index 4f7a701a7..e48d8bf57 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -38,6 +38,17 @@ std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const return pin_constraint_nets_[pin_constraint_id]; } +std::string PinConstraints::pin_net(const openfpga::BasicPort& pin) const { + std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); + for (const PinConstraintId& pin_constraint : pin_constraints()) { + if (pin == pin_constraint_pins_[pin_constraint]) { + constrained_net_name = net(pin_constraint); + break; + } + } + return constrained_net_name; +} + bool PinConstraints::empty() const { return 0 == pin_constraint_ids_.size(); } diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h index 8b3a977c0..e0ef7fe3f 100644 --- a/libopenfpga/libpcf/src/pin_constraints.h +++ b/libopenfpga/libpcf/src/pin_constraints.h @@ -52,6 +52,11 @@ class PinConstraints { /* Get the net to be constrained */ std::string net(const PinConstraintId& pin_constraint_id) const; + /* Find the net that is constrained on a pin + * TODO: this function will only return the first net found in the constraint list + */ + std::string pin_net(const openfpga::BasicPort& pin) const; + /* Check if there are any pin constraints */ bool empty() const; diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index d55a59834..e861e0748 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -135,13 +135,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, BasicPort module_clock_pin(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); /* If the clock port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name; - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { - if (module_clock_pin == pin_constraints.pin(pin_constraint)) { - constrained_net_name = pin_constraints.net(pin_constraint); - break; - } - } + std::string constrained_net_name = pin_constraints.pin_net(module_clock_pin); /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) @@ -179,13 +173,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, module_global_port.pins()[pin_id]); /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { - if (module_global_pin == pin_constraints.pin(pin_constraint)) { - constrained_net_name = pin_constraints.net(pin_constraint); - break; - } - } + std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); /* - If constrained to a given net in the benchmark, we connect the global pin to the net * - If constrained to an open net in the benchmark, we assign it to a default value diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index cc7b9fb98..7ac222ce6 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -385,13 +385,7 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, /* Regular reset port can be mapped by a net from user design */ if (false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { - if (module_global_pin == pin_constraints.pin(pin_constraint)) { - constrained_net_name = pin_constraints.net(pin_constraint); - break; - } - } + std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { From 02ca51d84bae2d57426b968793eb3047bc5a6f2f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 17:45:50 -0600 Subject: [PATCH 149/352] [Tool] Reorganize functions in full testbench generator to avoid big-chunk codes --- .../fpga_verilog/verilog_top_testbench.cpp | 117 ++++++++++++++++-- 1 file changed, 106 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 7ac222ce6..11f3777f2 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -258,22 +258,17 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp, } /******************************************************************** - * Wire the global ports of FPGA fabric to local wires + * Wire the global clock ports of FPGA fabric to local wires *******************************************************************/ static -void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const PinConstraints& pin_constraints, - const FabricGlobalPortInfo& fabric_global_port_info, - const SimulationSetting& simulation_parameters, - const bool& active_global_prog_reset, - const bool& active_global_prog_set) { +void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); - /* Connect global clock ports to operating or programming clock signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { @@ -318,6 +313,18 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } } +} + +/******************************************************************** + * Wire the global config done ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_config_done_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global configuration done ports to configuration done signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -342,6 +349,20 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, stimuli_config_done_port, 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } +} + +/******************************************************************** + * Wire the global reset ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_reset) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global reset ports to operating or programming reset signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -412,6 +433,19 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, } } } +} + +/******************************************************************** + * Wire the global set ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_set_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_set) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global set ports to operating or programming set signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -463,6 +497,18 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); } } +} + +/******************************************************************** + * Wire the regular global ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_regular_global_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { + /* Validate the file stream */ + valid_file_stream(fp); /* For the rest of global ports, wire them to constant signals */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -503,6 +549,55 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, std::vector default_values(module_port.get_width(), fabric_global_port_info.global_port_default_value(fabric_global_port)); print_verilog_wire_constant_values(fp, module_port, default_values); } +} + +/******************************************************************** + * Wire the global ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters, + const bool& active_global_prog_reset, + const bool& active_global_prog_set) { + /* Validate the file stream */ + valid_file_stream(fp); + + print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); + + print_verilog_top_testbench_global_clock_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info, + simulation_parameters); + + print_verilog_top_testbench_global_config_done_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info); + + + print_verilog_top_testbench_global_reset_ports_stimuli(fp, + module_manager, + top_module, + pin_constraints, + fabric_global_port_info, + active_global_prog_reset); + + print_verilog_top_testbench_global_set_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info, + active_global_prog_set); + + + print_verilog_top_testbench_regular_global_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info); print_verilog_comment(fp, std::string("----- End connecting global ports of FPGA fabric to stimuli -----")); } From 253422e7b7e848a97285656cc1964e57cf03bef5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 19:27:03 -0600 Subject: [PATCH 150/352] [Tool] Bugfix due to refactoring --- openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index e861e0748..a5647638a 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -137,16 +137,15 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, /* If the clock port name is in the pin constraints, we should wire it to the constrained pin */ std::string constrained_net_name = pin_constraints.pin_net(module_clock_pin); - /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ - if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) - || (true == benchmark_clock_port_names.empty())) { + /* If there is no clock in the benchmark, we assign it to a default value */ + if (true == benchmark_clock_port_names.empty()) { std::vector default_values(1, fabric_global_ports.global_port_default_value(global_port_id)); print_verilog_wire_constant_values(fp, module_clock_pin, default_values); continue; } std::string clock_name_to_connect; - if (!constrained_net_name.empty()) { + if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { clock_name_to_connect = constrained_net_name; } else { /* Otherwise, we must have a clear one-to-one clock net corresponding!!! */ From 6e9b24f9bf0473910fce97033da550825b27e267 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Apr 2021 19:56:30 -0600 Subject: [PATCH 151/352] [Tool] Patch the invalid pin constraint net name --- libopenfpga/libpcf/src/pin_constraints.cpp | 2 +- .../src/fpga_verilog/verilog_preconfig_top_module.cpp | 10 ++++++---- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index e48d8bf57..24d7571b7 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -39,7 +39,7 @@ std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const } std::string PinConstraints::pin_net(const openfpga::BasicPort& pin) const { - std::string constrained_net_name = std::string(PIN_CONSTRAINT_OPEN_NET); + std::string constrained_net_name; for (const PinConstraintId& pin_constraint : pin_constraints()) { if (pin == pin_constraint_pins_[pin_constraint]) { constrained_net_name = net(pin_constraint); diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index a5647638a..25b1abe5f 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -137,15 +137,16 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, /* If the clock port name is in the pin constraints, we should wire it to the constrained pin */ std::string constrained_net_name = pin_constraints.pin_net(module_clock_pin); - /* If there is no clock in the benchmark, we assign it to a default value */ - if (true == benchmark_clock_port_names.empty()) { + /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ + if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) + || (true == benchmark_clock_port_names.empty())) { std::vector default_values(1, fabric_global_ports.global_port_default_value(global_port_id)); print_verilog_wire_constant_values(fp, module_clock_pin, default_values); continue; } std::string clock_name_to_connect; - if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { + if (!constrained_net_name.empty()) { clock_name_to_connect = constrained_net_name; } else { /* Otherwise, we must have a clear one-to-one clock net corresponding!!! */ @@ -177,7 +178,8 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, /* - If constrained to a given net in the benchmark, we connect the global pin to the net * - If constrained to an open net in the benchmark, we assign it to a default value */ - if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { + if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) + && (!constrained_net_name.empty())) { BasicPort benchmark_pin(constrained_net_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1); print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false); } else { diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 11f3777f2..7a233de1a 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -409,7 +409,8 @@ void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ - if (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) { + if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) + && (!constrained_net_name.empty())) { BasicPort benchmark_pin(constrained_net_name, 1); print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, From 6550ea3dfaad0c5703bb30b44e91a20131ad43ad Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Apr 2021 12:02:49 -0600 Subject: [PATCH 152/352] [Tool] Rework pin constarint API to avoid expose raw data to judge for developers --- libopenfpga/libpcf/src/pin_constraints.cpp | 8 ++++++++ libopenfpga/libpcf/src/pin_constraints.h | 16 +++++++++++++++- .../verilog_preconfig_top_module.cpp | 8 ++++---- .../src/fpga_verilog/verilog_top_testbench.cpp | 4 ++-- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index 24d7571b7..bf7a3eca3 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -81,3 +81,11 @@ PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& bool PinConstraints::valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const { return ( size_t(pin_constraint_id) < pin_constraint_ids_.size() ) && ( pin_constraint_id == pin_constraint_ids_[pin_constraint_id] ); } + +bool PinConstraints::unconstrained_net(const std::string& net) const { + return net.empty(); +} + +bool PinConstraints::unmapped_net(const std::string& net) const { + return std::string(PIN_CONSTRAINT_OPEN_NET) == net; +} diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h index e0ef7fe3f..c68d53019 100644 --- a/libopenfpga/libpcf/src/pin_constraints.h +++ b/libopenfpga/libpcf/src/pin_constraints.h @@ -61,7 +61,6 @@ class PinConstraints { bool empty() const; public: /* Public Mutators */ - /* Reserve a number of design constraints to be memory efficent */ void reserve_pin_constraints(const size_t& num_pin_constraints); @@ -70,7 +69,22 @@ class PinConstraints { const std::string& net); public: /* Public invalidators/validators */ + /* Show if the pin constraint id is a valid for data queries */ bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const; + + /* Show if the net has no constraints (free to map to any pin) + * This function is used to identify the net name returned by APIs: + * - pin_net() + * - net() + */ + bool unconstrained_net(const std::string& net) const; + + /* Show if the net is defined specifically not to map to any pin + * This function is used to identify the net name returned by APIs: + * - pin_net() + * - net() + */ + bool unmapped_net(const std::string& net) const; private: /* Internal data */ /* Unique ids for each design constraint */ vtr::vector pin_constraint_ids_; diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 25b1abe5f..ece6df67a 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -138,7 +138,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, std::string constrained_net_name = pin_constraints.pin_net(module_clock_pin); /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ - if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) + if ( (true == pin_constraints.unmapped_net(constrained_net_name)) || (true == benchmark_clock_port_names.empty())) { std::vector default_values(1, fabric_global_ports.global_port_default_value(global_port_id)); print_verilog_wire_constant_values(fp, module_clock_pin, default_values); @@ -146,7 +146,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, } std::string clock_name_to_connect; - if (!constrained_net_name.empty()) { + if (!pin_constraints.unconstrained_net(constrained_net_name)) { clock_name_to_connect = constrained_net_name; } else { /* Otherwise, we must have a clear one-to-one clock net corresponding!!! */ @@ -178,8 +178,8 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, /* - If constrained to a given net in the benchmark, we connect the global pin to the net * - If constrained to an open net in the benchmark, we assign it to a default value */ - if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) - && (!constrained_net_name.empty())) { + if ( (false == pin_constraints.unconstrained_net(constrained_net_name)) + && (false == pin_constraints.unmapped_net(constrained_net_name))) { BasicPort benchmark_pin(constrained_net_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1); print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false); } else { diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 7a233de1a..4c7a48dda 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -409,8 +409,8 @@ void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ - if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) - && (!constrained_net_name.empty())) { + if ( (false == pin_constraints.unconstrained_net(constrained_net_name)) + && (false == pin_constraints.unmapped_net(constrained_net_name))) { BasicPort benchmark_pin(constrained_net_name, 1); print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, From 0b49c22682ed5a19116f1a3052df9bdcbeaa1944 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Apr 2021 16:11:11 -0600 Subject: [PATCH 153/352] [Tool] Now Verilog testbench generator support adding dedicated stimuli for reset signals from benchmarks --- libopenfpga/libpcf/src/pin_constraints.cpp | 11 +++ libopenfpga/libpcf/src/pin_constraints.h | 6 ++ openfpga/src/fpga_verilog/verilog_api.cpp | 2 + .../verilog_formal_random_top_testbench.cpp | 94 +++++++++++++++++++ .../verilog_formal_random_top_testbench.h | 4 + .../fpga_verilog/verilog_testbench_utils.cpp | 22 ++++- .../fpga_verilog/verilog_testbench_utils.h | 4 + .../fpga_verilog/verilog_top_testbench.cpp | 60 +++++++++++- .../utils/fabric_global_port_info_utils.cpp | 49 ++++++++++ .../src/utils/fabric_global_port_info_utils.h | 9 ++ 10 files changed, 258 insertions(+), 3 deletions(-) diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index bf7a3eca3..25cd1048d 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -49,6 +49,17 @@ std::string PinConstraints::pin_net(const openfpga::BasicPort& pin) const { return constrained_net_name; } +openfpga::BasicPort PinConstraints::net_pin(const std::string& net) const { + openfpga::BasicPort constrained_pin; + for (const PinConstraintId& pin_constraint : pin_constraints()) { + if (net == pin_constraint_nets_[pin_constraint]) { + constrained_pin = pin(pin_constraint); + break; + } + } + return constrained_pin; +} + bool PinConstraints::empty() const { return 0 == pin_constraint_ids_.size(); } diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h index c68d53019..3ea3aad2f 100644 --- a/libopenfpga/libpcf/src/pin_constraints.h +++ b/libopenfpga/libpcf/src/pin_constraints.h @@ -57,6 +57,12 @@ class PinConstraints { */ std::string pin_net(const openfpga::BasicPort& pin) const; + /* Find the pin that a net is constrained to + * If not found, the return port will be an invalid BasicPort + * TODO: this function will only return the first pin found in the constraint list + */ + openfpga::BasicPort net_pin(const std::string& net) const; + /* Check if there are any pin constraints */ bool empty() const; diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 424f85c42..46a81c96e 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -203,6 +203,8 @@ int fpga_verilog_testbench(const ModuleManager &module_manager, random_top_testbench_file_path, atom_ctx, netlist_annotation, + module_manager, + fabric_global_port_info, pin_constraints, simulation_setting, options.explicit_port_mapping()); diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index 860cc39a8..848970a30 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -19,6 +19,7 @@ #include "openfpga_atom_netlist_utils.h" #include "simulation_utils.h" +#include "fabric_global_port_info_utils.h" #include "verilog_constants.h" #include "verilog_writer_utils.h" @@ -168,6 +169,82 @@ void print_verilog_random_testbench_fpga_instance(std::fstream& fp, fp << std::endl; } +/******************************************************************** + * Generate random stimulus for the reset port + * This function is designed to drive the reset port of a benchmark module + * The reset signal will be + * - enabled in the 1st clock cycle + * - disabled in the rest of clock cycles + *******************************************************************/ +static +void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, + const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const std::vector& clock_port_names, + const BasicPort& clock_port) { + valid_file_stream(fp); + + print_verilog_comment(fp, "----- Begin reset signal generation -----"); + + for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { + /* Bypass non-input atom blocks ! */ + if (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) { + continue; + } + + /* The block may be renamed as it contains special characters which violate Verilog syntax */ + std::string block_name = atom_ctx.nlist.block_name(atom_blk); + if (true == netlist_annotation.is_block_renamed(atom_blk)) { + block_name = netlist_annotation.block_name(atom_blk); + } + + /* Bypass clock ports because their stimulus cannot be random */ + if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + continue; + } + + /* Bypass any constained net that are mapped to a global port of the FPGA fabric + * because their stimulus cannot be random + */ + if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + continue; + } + + /* Generete stimuli for this net which is how reset signal works */ + BasicPort reset_port(block_name, 1); + size_t initial_value = 1; + if (1 == global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name)))) { + initial_value = 0; + } + + fp << "initial" << std::endl; + fp << "\tbegin" << std::endl; + fp << "\t"; + std::vector initial_values(reset_port.get_width(), initial_value); + fp << "\t"; + fp << generate_verilog_port_constant_values(reset_port, initial_values); + fp << ";" << std::endl; + + /* Flip the reset at the second negative edge of the clock port + * So the generic reset stimuli is applicable to both synchronous reset and asynchronous reset + * This is because the reset is activated in a complete clock cycle + * This gaurantees that even for synchronous reset, the reset can be sensed in the 1st rising/falling + * edge of the clock signal + */ + fp << "\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" << std::endl; + fp << "\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" << std::endl; + print_verilog_wire_connection(fp, reset_port, reset_port, true); + fp << "\tend" << std::endl; + } + + print_verilog_comment(fp, "----- End reset signal generation -----"); + + fp << std::endl; +} + /********************************************************************* * Top-level function in this file: * Create a Verilog testbench using random input vectors @@ -197,6 +274,8 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, const std::string& verilog_fname, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, const PinConstraints& pin_constraints, const SimulationSetting& simulation_parameters, const bool& explicit_port_mapping) { @@ -240,8 +319,23 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, pin_constraints, simulation_parameters, clock_ports); + /* TODO: use the first clock now because we do not have information how the reset is + * correlated to clock ports. Once we have such information, the limitation should be removed! + */ + print_verilog_random_testbench_reset_stimuli(fp, + atom_ctx, + netlist_annotation, + module_manager, + global_ports, + pin_constraints, + clock_port_names, + clock_ports[0]); + print_verilog_testbench_random_stimuli(fp, atom_ctx, netlist_annotation, + module_manager, + global_ports, + pin_constraints, clock_port_names, std::string(CHECKFLAG_PORT_POSTFIX), clock_ports); diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h index d89652df9..6dd4f0310 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h @@ -7,6 +7,8 @@ #include #include "vpr_context.h" #include "pin_constraints.h" +#include "module_manager.h" +#include "fabric_global_port_info.h" #include "simulation_setting.h" /******************************************************************** @@ -20,6 +22,8 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, const std::string& verilog_fname, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, const PinConstraints& pin_constraints, const SimulationSetting& simulation_parameters, const bool& explicit_port_mapping); diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index b445e07f9..3329d33cf 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -21,6 +21,7 @@ #include "verilog_port_types.h" #include "module_manager_utils.h" +#include "fabric_global_port_info_utils.h" #include "verilog_constants.h" #include "verilog_writer_utils.h" @@ -537,6 +538,9 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp, void print_verilog_testbench_random_stimuli(std::fstream& fp, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const std::vector& clock_port_names, const std::string& check_flag_port_postfix, const std::vector& clock_ports) { @@ -560,11 +564,18 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, block_name = netlist_annotation.block_name(atom_blk); } - /* Bypass clock ports */ + /* Bypass clock ports because their stimulus cannot be random */ if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { continue; } + /* Bypass any constained net that are mapped to a global port of the FPGA fabric + * because their stimulus cannot be random + */ + if (true == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + continue; + } + /* TODO: find the clock inputs will be initialized later */ if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { fp << "\t\t" << block_name << " <= 1'b0;" << std::endl; @@ -620,11 +631,18 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, block_name = netlist_annotation.block_name(atom_blk); } - /* Bypass clock ports */ + /* Bypass clock ports because their stimulus cannot be random */ if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { continue; } + /* Bypass any constained net that are mapped to a global port of the FPGA fabric + * because their stimulus cannot be random + */ + if (true == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + continue; + } + /* TODO: find the clock inputs will be initialized later */ if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { fp << "\t\t" << block_name << " <= $random;" << std::endl; diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index a2eca17cd..0eb77bda9 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -12,6 +12,7 @@ #include "vpr_context.h" #include "io_location_map.h" #include "vpr_netlist_annotation.h" +#include "fabric_global_port_info.h" #include "pin_constraints.h" #include "simulation_setting.h" @@ -84,6 +85,9 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp, void print_verilog_testbench_random_stimuli(std::fstream& fp, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const std::vector& clock_port_names, const std::string& check_flag_port_postfix, const std::vector& clock_ports); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 4c7a48dda..d58a2c730 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -47,7 +47,6 @@ constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task"; constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start"; -constexpr int TOP_TESTBENCH_MAGIC_NUMBER_FOR_SIMULATION_TIME = 200; constexpr char* TOP_TESTBENCH_ERROR_COUNTER = "nb_error"; constexpr char* TOP_TB_RESET_PORT_NAME = "greset"; @@ -1931,6 +1930,54 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp, } } +/******************************************************************** + * Connect proper stimuli to the reset port + * This function is designed to drive the reset port of a benchmark module + *******************************************************************/ +static +void print_verilog_top_testbench_reset_stimuli(std::fstream& fp, + const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const std::vector& clock_port_names) { + valid_file_stream(fp); + + print_verilog_comment(fp, "----- Begin reset signal generation -----"); + + for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { + /* Bypass non-input atom blocks ! */ + if (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) { + continue; + } + + /* The block may be renamed as it contains special characters which violate Verilog syntax */ + std::string block_name = atom_ctx.nlist.block_name(atom_blk); + if (true == netlist_annotation.is_block_renamed(atom_blk)) { + block_name = netlist_annotation.block_name(atom_blk); + } + + /* Bypass clock ports because their stimulus cannot be random */ + if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + continue; + } + + /* Bypass any constained net that are mapped to a global port of the FPGA fabric + * because their stimulus cannot be random + */ + if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + continue; + } + + /* Connect stimuli to greset with an optional inversion, depending on the default value */ + BasicPort reset_port(block_name, 1); + print_verilog_wire_connection(fp, reset_port, + BasicPort(TOP_TB_RESET_PORT_NAME, 1), + 1 == global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name)))); + } +} + /******************************************************************** * Add auto-check codes for the full testbench * in particular for the configuration phase: @@ -2164,9 +2211,20 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, top_module); } + /* Add stimuli for reset, set, clock and iopad signals */ + print_verilog_top_testbench_reset_stimuli(fp, + atom_ctx, + netlist_annotation, + module_manager, + global_ports, + pin_constraints, + clock_port_names); print_verilog_testbench_random_stimuli(fp, atom_ctx, netlist_annotation, + module_manager, + global_ports, + pin_constraints, clock_port_names, std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), std::vector(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1))); diff --git a/openfpga/src/utils/fabric_global_port_info_utils.cpp b/openfpga/src/utils/fabric_global_port_info_utils.cpp index 3200a8fbd..9fbd707c5 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.cpp +++ b/openfpga/src/utils/fabric_global_port_info_utils.cpp @@ -11,6 +11,8 @@ #include "vtr_assert.h" #include "vtr_log.h" +#include "openfpga_naming.h" + #include "fabric_global_port_info_utils.h" /* begin namespace openfpga */ @@ -58,4 +60,51 @@ std::vector find_fabric_global_programming_set_ports(const F return global_prog_set_ports; } +/******************************************************************** + * Identify if a port is in the list of fabric global port + * and its functionality is a reset port which is not used for programming FPGAs + *******************************************************************/ +bool port_is_fabric_global_reset_port(const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, + const BasicPort& port) { + /* Find the top_module: the fabric global ports are always part of the ports of the top module */ + ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + + for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { + if ( (false == fabric_global_port_info.global_port_is_reset(fabric_global_port_id)) + || (true == fabric_global_port_info.global_port_is_prog(fabric_global_port_id))) { + continue; + } + + BasicPort module_global_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(fabric_global_port_id)); + if ( (true == module_global_port.mergeable(port)) + && (true == module_global_port.contained(port)) ) { + return true; + } + } + + return false; +} + +/******************************************************************** + * Find a global port with a given name + *******************************************************************/ +FabricGlobalPortId find_fabric_global_port(const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, + const BasicPort& port) { + /* Find the top_module: the fabric global ports are always part of the ports of the top module */ + ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + + for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { + BasicPort module_global_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(fabric_global_port_id)); + if ( (true == module_global_port.mergeable(port)) + && (true == module_global_port.contained(port)) ) { + return fabric_global_port_id; + } + } + return FabricGlobalPortId::INVALID(); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/fabric_global_port_info_utils.h b/openfpga/src/utils/fabric_global_port_info_utils.h index 457c0018e..99611bc8b 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.h +++ b/openfpga/src/utils/fabric_global_port_info_utils.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include "fabric_global_port_info.h" +#include "module_manager.h" /******************************************************************** * Function declaration @@ -18,6 +19,14 @@ std::vector find_fabric_global_programming_reset_ports(const std::vector find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info); +bool port_is_fabric_global_reset_port(const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, + const BasicPort& port); + +FabricGlobalPortId find_fabric_global_port(const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, + const BasicPort& port); + } /* end namespace openfpga */ #endif From beed1ce31e40540d42775a709bcab371a1bbeb44 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 08:38:09 -0600 Subject: [PATCH 154/352] replace hyperlink with more stable :ref: link --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index cbc161971..6e55bbddf 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the ``user_defined_template.v`` file. +Through this tutorial, we will show how and when to use the :ref:`cmdoption-arg-user_defined_templates.v` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The `user_defined_template.v`_ file can be found starting from the root directory and entering: +The :ref:`cmdoption-arg-user_defined_templates.v` file can be found starting from the root directory and entering: .. code-block:: bash @@ -167,4 +167,3 @@ Finally, rerun this command from the OpenFPGA root directory to ensure it is wor python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -.. _user_defined_template.v: https://openfpga.readthedocs.io/en/master/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v From 291638ee0f05f14bf074ddb69759eb2397114cea Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 08:45:02 -0600 Subject: [PATCH 155/352] Trying to resolve hyperlink to right location --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 6e55bbddf..67e7fd9d2 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the :ref:`cmdoption-arg-user_defined_templates.v` file. +Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :ref:`cmdoption-arg-user_defined_templates.v` file can be found starting from the root directory and entering: +The :ref:`user_defined_templates.v` file can be found starting from the root directory and entering: .. code-block:: bash From 5010fb1e7ffdcd74fb934a36b7ad4c59ed2d9cba Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 08:52:05 -0600 Subject: [PATCH 156/352] Update hyperlinks --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 67e7fd9d2..6e55bbddf 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v` file. +Through this tutorial, we will show how and when to use the :ref:`cmdoption-arg-user_defined_templates.v` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :ref:`user_defined_templates.v` file can be found starting from the root directory and entering: +The :ref:`cmdoption-arg-user_defined_templates.v` file can be found starting from the root directory and entering: .. code-block:: bash From fcb7ee3283e1c9238a80e34c39107a3d6710a1ce Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:05:30 -0600 Subject: [PATCH 157/352] Update to properly reference fabric netlist page --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 6e55bbddf..f94b9e22c 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the :ref:`cmdoption-arg-user_defined_templates.v` file. +Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v ` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :ref:`cmdoption-arg-user_defined_templates.v` file can be found starting from the root directory and entering: +The :ref:`user_defined_templates.v ` file can be found starting from the root directory and entering: .. code-block:: bash From f8810940c35d4597f05c5a75c64b9fe513fd818a Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:10:17 -0600 Subject: [PATCH 158/352] Update links --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index f94b9e22c..f0ea3fa4e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v ` file. +Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v ` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :ref:`user_defined_templates.v ` file can be found starting from the root directory and entering: +The :ref:`user_defined_templates.v ` file can be found starting from the root directory and entering: .. code-block:: bash From cd6beb57898adec6fa402cbb8dfc88a42f6f3630 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:14:47 -0600 Subject: [PATCH 159/352] Add one more link to fabric_netlists --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index f0ea3fa4e..a1b59d27e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -74,7 +74,7 @@ This error can be resolved by replacing the **LINE187** of ``k6_frac_N10_adder_c -The above line provides a path to generate the ``user_defined_template.v`` file. +The above line provides a path to generate the :ref:`user_defined_templates.v ` file. Now we can return to the root directory and run this command again: .. code-block:: bash From 86c856d35a25cb55045e52a4117dd4988d53d295 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:25:54 -0600 Subject: [PATCH 160/352] Fix reference links --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index a1b59d27e..ea874f15f 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,7 +5,7 @@ Introduction and Setup **In this tutorial, we will** - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this tutorial, we will show how and when to use the :ref:`user_defined_templates.v ` file. +Through this tutorial, we will show how and when to use the :ref:`user_defined_template.v ` file. To begin the tutorial, we start with a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: @@ -74,7 +74,7 @@ This error can be resolved by replacing the **LINE187** of ``k6_frac_N10_adder_c -The above line provides a path to generate the :ref:`user_defined_templates.v ` file. +The above line provides a path to generate the :ref:`user_defined_template.v ` file. Now we can return to the root directory and run this command again: .. code-block:: bash @@ -85,7 +85,7 @@ The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :ref:`user_defined_templates.v ` file can be found starting from the root directory and entering: +The :ref:`user_defined_template.v ` file can be found starting from the root directory and entering: .. code-block:: bash From 8431337f3980f34fa8982b7bb3de9d284e55d77b Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:36:13 -0600 Subject: [PATCH 161/352] Fix grammar errors in fig captions and elsewhere --- .../tutorials/arch_modeling/spypads_tutorial.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index 973a41f9f..b809a3b23 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -10,7 +10,7 @@ Introduction - Modify an existing architecture to incorporate Spypads - Verify correctness through GTKWave -Through this tutorial, we will show how to create Spypads in OpenFPGA. +Through this tutorial, we will show how to create spypads in OpenFPGA. Spypads are physical output pins on a FPGA chip through which you can read out internal signals when doing silicon-level debugging. The XML syntax for spypads and other global signals can be found on our :ref:`circuit_library` documentation page. @@ -35,7 +35,7 @@ file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_op emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml -In this architecture file, the output ports of a 6-input Look Up Table (LUT) are defined as spypads using the XML syntax ``is_global`` and ``is_io``. As a result, all of the outputs from the 6-input LUT will be visible in the top-level module. The output ports to the 6-input LUT are declared from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172**. +In this architecture file, the output ports of a 6-input lookup table (LUT) are defined as spypads using the XML syntax ``is_global`` and ``is_io``. As a result, all of the outputs from the 6-input LUT will be visible in the top-level module. The output ports to the 6-input LUT are declared from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172**. .. code-block:: xml @@ -116,7 +116,7 @@ The file will look like this when finished: [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= - #LINE44 vpr_fpga_verilog_formal_verification_top_netlist= + #vpr_fpga_verilog_formal_verification_top_netlist= Our OpenFPGA task will now run the full testbench. We run the task with the following command from the root directory of OpenFPGA: @@ -231,9 +231,9 @@ The waveforms will appear similar to :numref:`fig_spypad_waves` .. _fig_spypad_waves: .. figure:: ./figures/spypad_waveforms.png - :width: 75% + :width: 100% - Waveforms of ``frac_lut6`` Spypads + Waveforms of ``frac_lut6`` spypads Building Spypads ~~~~~~~~~~~~~~~~ @@ -322,9 +322,9 @@ The waveform should have some changes to its value. An example of what it may lo .. _fig_spy_adder: .. figure:: ./figures/spyadder_waveform.png - :scale: 100% + :width: 100% - Waveforms of ``sumout`` Spypad + Waveforms of ``sumout`` spypad Conclusion ~~~~~~~~~~ From bc6e9746c2c8e659cae6e8a540a18a741cc06232 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 09:48:42 -0600 Subject: [PATCH 162/352] Fix more grammar mistakes --- docs/source/tutorials/arch_modeling/spypads_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index b809a3b23..dc82673b0 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -5,9 +5,9 @@ Introduction ~~~~~~~~~~~~ **In this tutorial, we will** - - Show the XML Syntax for Global Outputs - - Showcase an example with Spypads - - Modify an existing architecture to incorporate Spypads + - Show the XML syntax for global outputs + - Showcase an example with spypads + - Modify an existing architecture to incorporate spypads - Verify correctness through GTKWave Through this tutorial, we will show how to create spypads in OpenFPGA. From 5364b94cf8dca11f3e56e464140b628fd549c4ec Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 13:42:12 -0600 Subject: [PATCH 163/352] [Tool] Update bitstream setting parser/writer to support interconnect-related syntax --- .../libarchopenfpga/src/bitstream_setting.cpp | 41 ++++++++++++++ .../libarchopenfpga/src/bitstream_setting.h | 31 +++++++++++ .../src/bitstream_setting_fwd.h | 2 + .../src/read_xml_bitstream_setting.cpp | 35 ++++++++++-- .../src/write_xml_bitstream_setting.cpp | 53 ++++++++++++++++++- 5 files changed, 157 insertions(+), 5 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/bitstream_setting.cpp b/libopenfpga/libarchopenfpga/src/bitstream_setting.cpp index f7a773dad..f239a78b3 100644 --- a/libopenfpga/libarchopenfpga/src/bitstream_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/bitstream_setting.cpp @@ -16,6 +16,10 @@ BitstreamSetting::bitstream_pb_type_setting_range BitstreamSetting::pb_type_sett return vtr::make_range(pb_type_setting_ids_.begin(), pb_type_setting_ids_.end()); } +BitstreamSetting::bitstream_interconnect_setting_range BitstreamSetting::interconnect_settings() const { + return vtr::make_range(interconnect_setting_ids_.begin(), interconnect_setting_ids_.end()); +} + /************************************************************************ * Constructors ***********************************************************************/ @@ -61,6 +65,25 @@ size_t BitstreamSetting::bitstream_offset(const BitstreamPbTypeSettingId& pb_typ return bitstream_offsets_[pb_type_setting_id]; } +std::string BitstreamSetting::interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); + return interconnect_names_[interconnect_setting_id]; +} + +std::vector BitstreamSetting::parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); + return interconnect_parent_pb_type_names_[interconnect_setting_id]; +} + +std::vector BitstreamSetting::parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); + return interconnect_parent_mode_names_[interconnect_setting_id]; +} + +std::string BitstreamSetting::default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); + return interconnect_default_paths_[interconnect_setting_id]; +} /************************************************************************ * Public Mutators @@ -95,6 +118,20 @@ void BitstreamSetting::set_bitstream_offset(const BitstreamPbTypeSettingId& pb_t bitstream_offsets_[pb_type_setting_id] = offset; } +BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_setting(const std::string& interconnect_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& default_path) { + BitstreamInterconnectSettingId interc_setting_id = BitstreamInterconnectSettingId(interconnect_setting_ids_.size()); + interconnect_setting_ids_.push_back(interc_setting_id); + interconnect_names_.push_back(interconnect_name); + interconnect_parent_pb_type_names_.push_back(parent_pb_type_names); + interconnect_parent_mode_names_.push_back(parent_mode_names); + interconnect_default_paths_.push_back(default_path); + + return interc_setting_id; +} + /************************************************************************ * Public Validators ***********************************************************************/ @@ -102,4 +139,8 @@ bool BitstreamSetting::valid_bitstream_pb_type_setting_id(const BitstreamPbTypeS return ( size_t(pb_type_setting_id) < pb_type_setting_ids_.size() ) && ( pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id] ); } +bool BitstreamSetting::valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const { + return ( size_t(interconnect_setting_id) < interconnect_setting_ids_.size() ) && ( interconnect_setting_id == interconnect_setting_ids_[interconnect_setting_id] ); +} + } /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/bitstream_setting.h b/libopenfpga/libarchopenfpga/src/bitstream_setting.h index a972bb6c4..63cb9092b 100644 --- a/libopenfpga/libarchopenfpga/src/bitstream_setting.h +++ b/libopenfpga/libarchopenfpga/src/bitstream_setting.h @@ -16,6 +16,10 @@ namespace openfpga { /******************************************************************** * A data structure to describe bitstream settings + * + * This data structure includes following types of settings: + * - Pb type: include definiting hard coded bitstream for pb_types (LUT or configurable pb_type for mode selection) + * - Interconnect: include defining default paths for routing multiplexers in pb_types * * Typical usage: * -------------- @@ -27,12 +31,15 @@ namespace openfpga { class BitstreamSetting { public: /* Types */ typedef vtr::vector::const_iterator bitstream_pb_type_setting_iterator; + typedef vtr::vector::const_iterator bitstream_interconnect_setting_iterator; /* Create range */ typedef vtr::Range bitstream_pb_type_setting_range; + typedef vtr::Range bitstream_interconnect_setting_range; public: /* Constructors */ BitstreamSetting(); public: /* Accessors: aggregates */ bitstream_pb_type_setting_range pb_type_settings() const; + bitstream_interconnect_setting_range interconnect_settings() const; public: /* Public Accessors */ std::string pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const; std::vector parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const; @@ -41,6 +48,10 @@ class BitstreamSetting { std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const; bool is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const; size_t bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::string interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::vector parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::vector parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::string default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const; public: /* Public Mutators */ BitstreamPbTypeSettingId add_bitstream_pb_type_setting(const std::string& pb_type_name, const std::vector& parent_pb_type_names, @@ -51,9 +62,19 @@ class BitstreamSetting { const bool& is_mode_select_bitstream); void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id, const size_t& offset); + + BitstreamInterconnectSettingId add_bitstream_interconnect_setting(const std::string& interconnect_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& default_path); public: /* Public Validators */ bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const; + bool valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const; private: /* Internal data */ + /* Pb type -related settings + * - Paths to a pb_type in the pb_graph + * - Bitstream source, data_type, offsets etc. + */ vtr::vector pb_type_setting_ids_; vtr::vector pb_type_names_; vtr::vector> parent_pb_type_names_; @@ -64,6 +85,16 @@ class BitstreamSetting { vtr::vector is_mode_select_bitstreams_; /* The offset that the bitstream is applied to the original bitstream of a pb_type */ vtr::vector bitstream_offsets_; + + /* Interconnect-related settings: + * - Name of interconnect under a given pb_type + * - The default path to be considered for a given interconnect during bitstream generation + */ + vtr::vector interconnect_setting_ids_; + vtr::vector interconnect_names_; + vtr::vector> interconnect_parent_pb_type_names_; + vtr::vector> interconnect_parent_mode_names_; + vtr::vector interconnect_default_paths_; }; } /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/bitstream_setting_fwd.h b/libopenfpga/libarchopenfpga/src/bitstream_setting_fwd.h index 009bcbfed..d5bb618e1 100644 --- a/libopenfpga/libarchopenfpga/src/bitstream_setting_fwd.h +++ b/libopenfpga/libarchopenfpga/src/bitstream_setting_fwd.h @@ -13,8 +13,10 @@ #include "vtr_strong_id.h" struct bitstream_pb_type_setting_id_tag; +struct bitstream_interconnect_setting_id_tag; typedef vtr::StrongId BitstreamPbTypeSettingId; +typedef vtr::StrongId BitstreamInterconnectSettingId; /* Short declaration of class */ class BitstreamSetting; diff --git a/libopenfpga/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libopenfpga/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 181ee531c..05ffc492d 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -50,6 +50,26 @@ void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type, bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset); } +/******************************************************************** + * Parse XML description for a pb_type annotation under a XML node + *******************************************************************/ +static +void read_xml_bitstream_interconnect_setting(pugi::xml_node& xml_pb_type, + const pugiutil::loc_data& loc_data, + openfpga::BitstreamSetting& bitstream_setting) { + const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string(); + const std::string& default_path_attr = get_attribute(xml_pb_type, "default_path", loc_data).as_string(); + + /* Parse the attributes for operating pb_type */ + openfpga::PbParser operating_pb_parser(name_attr); + + /* Add to bitstream setting */ + bitstream_setting.add_bitstream_interconnect_setting(operating_pb_parser.leaf(), + operating_pb_parser.parents(), + operating_pb_parser.modes(), + default_path_attr); +} + /******************************************************************** * Parse XML codes about to an object *******************************************************************/ @@ -60,12 +80,19 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node, /* Iterate over the children under this node, * each child should be named after */ - for (pugi::xml_node xml_pb_type : Node.children()) { + for (pugi::xml_node xml_child : Node.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_pb_type.name() != std::string("pb_type")) { - bad_tag(xml_pb_type, loc_data, Node, {"pb_type"}); + if ( (xml_child.name() != std::string("pb_type")) + && (xml_child.name() != std::string("interconnect")) ) { + bad_tag(xml_child, loc_data, Node, {"pb_type | interconnect"}); + } + + if (xml_child.name() == std::string("pb_type")) { + read_xml_bitstream_pb_type_setting(xml_child, loc_data, bitstream_setting); + } else { + VTR_ASSERT_SAFE(xml_child.name() == std::string("interconnect")); + read_xml_bitstream_interconnect_setting(xml_child, loc_data, bitstream_setting); } - read_xml_bitstream_pb_type_setting(xml_pb_type, loc_data, bitstream_setting); } return bitstream_setting; diff --git a/libopenfpga/libarchopenfpga/src/write_xml_bitstream_setting.cpp b/libopenfpga/libarchopenfpga/src/write_xml_bitstream_setting.cpp index 51600cf4f..1754fbc4b 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_bitstream_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_bitstream_setting.cpp @@ -39,6 +39,31 @@ std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::Bi return hie_name; } +/******************************************************************** + * Generate the full hierarchy name for an interconnect in bitstream setting + *******************************************************************/ +static +std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { + /* Iterate over the parent_pb_type and modes names, they should well match */ + VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size()); + + std::string hie_name; + + for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size(); ++i) { + hie_name += bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i]; + hie_name += std::string("["); + hie_name += bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i]; + hie_name += std::string("]"); + hie_name += std::string("."); + } + + /* Add the leaf pb_type */ + hie_name += bitstream_setting.interconnect_name(bitstream_interc_setting_id); + + return hie_name; +} + /******************************************************************** * A writer to output a bitstream pb_type setting to XML format *******************************************************************/ @@ -63,6 +88,27 @@ void write_xml_bitstream_pb_type_setting(std::fstream& fp, fp << "/>" << "\n"; } +/******************************************************************** + * A writer to output a bitstream interconnect setting to XML format + *******************************************************************/ +static +void write_xml_bitstream_interconnect_setting(std::fstream& fp, + const char* fname, + const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + fp << "\t" << "" << "\n"; +} + /******************************************************************** * A writer to output a bitstream setting to XML format *******************************************************************/ @@ -76,11 +122,16 @@ void write_xml_bitstream_setting(std::fstream& fp, */ fp << "" << "\n"; - /* Write clock settings */ + /* Write pb_type -related settings */ for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) { write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, bitstream_pb_type_setting_id); } + /* Write interconnect -related settings */ + for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) { + write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting, bitstream_interc_setting_id); + } + /* Write the root node */ fp << "" << "\n"; } From 986ea492f6ca463c7a64724dd266a92174d7d9a4 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 19 Apr 2021 14:16:40 -0600 Subject: [PATCH 164/352] Fix grammar line 38: lookup table ->Look-Up Table --- docs/source/tutorials/arch_modeling/spypads_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst index dc82673b0..5ffd5ddae 100644 --- a/docs/source/tutorials/arch_modeling/spypads_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/spypads_tutorial.rst @@ -35,7 +35,7 @@ file. We can view ``k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_op emacs openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_spypad_40nm_openfpga.xml -In this architecture file, the output ports of a 6-input lookup table (LUT) are defined as spypads using the XML syntax ``is_global`` and ``is_io``. As a result, all of the outputs from the 6-input LUT will be visible in the top-level module. The output ports to the 6-input LUT are declared from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172**. +In this architecture file, the output ports of a 6-input Look-Up Table (LUT) are defined as spypads using the XML syntax ``is_global`` and ``is_io``. As a result, all of the outputs from the 6-input LUT will be visible in the top-level module. The output ports to the 6-input LUT are declared from **LINE181** to **LINE183** and belong to the ``frac_lut6_spypad`` ``circuit_model`` that begins at **LINE172**. .. code-block:: xml From 0aec30bac6a33e5d14abbdb550be6c9a1f9699c0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 15:53:33 -0600 Subject: [PATCH 165/352] [Tool] Update FPGA core engine to support mux default path overloading through bitstream setting file --- .../annotation/annotate_bitstream_setting.cpp | 141 +++++++++++++++++- .../annotation/annotate_bitstream_setting.h | 1 + .../annotation/vpr_bitstream_annotation.cpp | 16 ++ .../src/annotation/vpr_bitstream_annotation.h | 9 ++ openfpga/src/base/openfpga_link_arch.cpp | 2 + .../fpga_bitstream/build_device_bitstream.cpp | 1 + .../fpga_bitstream/build_grid_bitstream.cpp | 38 +++-- .../src/fpga_bitstream/build_grid_bitstream.h | 2 + 8 files changed, 195 insertions(+), 15 deletions(-) diff --git a/openfpga/src/annotation/annotate_bitstream_setting.cpp b/openfpga/src/annotation/annotate_bitstream_setting.cpp index 48002a08b..a51e73fde 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.cpp +++ b/openfpga/src/annotation/annotate_bitstream_setting.cpp @@ -12,6 +12,9 @@ #include "vtr_assert.h" #include "vtr_log.h" +/* Headers from openfpgautil library */ +#include "openfpga_tokenizer.h" + #include "pb_type_utils.h" #include "annotate_bitstream_setting.h" @@ -23,9 +26,10 @@ namespace openfpga { * - Find the pb_type and link to the bitstream source * - Find the pb_type and link to the bitstream content *******************************************************************/ -int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - VprBitstreamAnnotation& vpr_bitstream_annotation) { +static +int annotate_bitstream_pb_type_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + VprBitstreamAnnotation& vpr_bitstream_annotation) { for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) { /* Get the full name of pb_type */ @@ -95,4 +99,135 @@ int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Annotate bitstream setting based on VPR device information + * - Find the interconnect and link to the default path id + *******************************************************************/ +static +int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + + for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) { + /* Get the full name of pb_type */ + std::vector target_pb_type_names; + std::vector target_pb_mode_names; + + target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id); + target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_interc_setting_id); + /* Kick out the last mode so that we can use an existing function search the pb_type in graph */ + std::string expected_physical_mode_name = target_pb_mode_names.back(); + target_pb_mode_names.pop_back(); + + std::string interconnect_name = bitstream_setting.interconnect_name(bitstream_interc_setting_id); + std::string expected_input_path = bitstream_setting.default_path(bitstream_interc_setting_id); + + /* Pb type information are located at the logic_block_types in the device context of VPR + * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + */ + bool link_success = false; + + for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + /* By pass nullptr for pb_type head */ + if (nullptr == lb_type.pb_type) { + continue; + } + /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) { + continue; + } + /* Match the name in the top-level, we go further to search the pb_type in the graph */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, + target_pb_mode_names); + if (nullptr == target_pb_type) { + continue; + } + + /* Found one, build annotation */ + t_mode* physical_mode = vpr_device_annotation.physical_mode(target_pb_type); + + VTR_ASSERT(nullptr != physical_mode); + /* Ensure that the annotation is only applicable to physical mode */ + if (std::string(physical_mode->name) != expected_physical_mode_name) { + VTR_LOG_ERROR("The physical mode '%s' under pb_type '%s' does not match in the bitstream setting '%s'!\n", + physical_mode->name, + target_pb_type->name, + expected_physical_mode_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the interconnect name under the physical mode of a physical pb_type */ + t_interconnect* pb_interc = find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); + + if (nullptr == pb_interc) { + VTR_LOG_ERROR("Unable to find interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", + interconnect_name.c_str(), + physical_mode->name, + target_pb_type->name); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the default path and spot the path id from the input string recorded */ + StringToken input_string_tokenizer(std::string(pb_interc->input_string)); + std::vector input_paths = input_string_tokenizer.split(' '); + size_t input_path_id = input_paths.size(); + for (size_t ipath = 0; ipath < input_paths.size(); ++ipath) { + if (expected_input_path == input_paths[ipath]) { + input_path_id = ipath; + break; + } + } + /* If the input_path id is invalid, error out! */ + if (input_path_id == input_paths.size()) { + VTR_LOG_ERROR("Invalid default path '%s' for interconnect '%s' which inputs are '%s'\n", + expected_input_path.c_str(), + interconnect_name.c_str(), + pb_interc->input_string); + return CMD_EXEC_FATAL_ERROR; + } + + vpr_bitstream_annotation.set_interconnect_default_path_id(pb_interc, input_path_id); + + link_success = true; + } + + /* If fail to link bitstream setting to architecture, error out immediately */ + if (false == link_success) { + VTR_LOG_ERROR("Fail to find an interconnect '%s' with default path '%s', which is defined in bitstream setting from VPR architecture description\n", + interconnect_name.c_str(), + expected_input_path.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Annotate bitstream setting based on VPR device information + * - Fill pb_type -related mapping + * - Fill interconnect -related mapping + *******************************************************************/ +int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + + int status = CMD_EXEC_SUCCESS; + + status = annotate_bitstream_pb_type_setting(bitstream_setting, + vpr_device_ctx, + vpr_bitstream_annotation); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + + status = annotate_bitstream_interconnect_setting(bitstream_setting, + vpr_device_ctx, vpr_device_annotation, + vpr_bitstream_annotation); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_bitstream_setting.h b/openfpga/src/annotation/annotate_bitstream_setting.h index 053ca2fbe..45d6316dd 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.h +++ b/openfpga/src/annotation/annotate_bitstream_setting.h @@ -16,6 +16,7 @@ namespace openfpga { int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, VprBitstreamAnnotation& vpr_bitstream_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.cpp b/openfpga/src/annotation/vpr_bitstream_annotation.cpp index 3361d598c..38842cbff 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.cpp +++ b/openfpga/src/annotation/vpr_bitstream_annotation.cpp @@ -4,6 +4,7 @@ #include "vtr_log.h" #include "vtr_assert.h" #include "vpr_bitstream_annotation.h" +#include "mux_bitstream_constants.h" /* namespace openfpga begins */ namespace openfpga { @@ -78,6 +79,16 @@ size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* p return 0; } +size_t VprBitstreamAnnotation::interconnect_default_path_id(t_interconnect* interconnect) const { + auto result = interconnect_default_path_ids_.find(interconnect); + if (result != interconnect_default_path_ids_.end()) { + return result->second; + } + + /* Not found, return an invalid input id */ + return DEFAULT_PATH_ID; +} + /************************************************************************ * Public mutators ***********************************************************************/ @@ -111,4 +122,9 @@ void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset(t_pb_type* mode_select_bitstream_offsets_[pb_type] = offset; } +void VprBitstreamAnnotation::set_interconnect_default_path_id(t_interconnect* interconnect, + const size_t& default_path_id) { + interconnect_default_path_ids_[interconnect] = default_path_id; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.h b/openfpga/src/annotation/vpr_bitstream_annotation.h index c562e4aa2..134530f25 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.h +++ b/openfpga/src/annotation/vpr_bitstream_annotation.h @@ -38,6 +38,7 @@ class VprBitstreamAnnotation { e_bitstream_source_type pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const; std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const; size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const; + size_t interconnect_default_path_id(t_interconnect* interconnect) const; public: /* Public mutators */ void set_pb_type_bitstream_source(t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source); @@ -52,6 +53,8 @@ class VprBitstreamAnnotation { const std::string& bitstream_content); void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type, const size_t& offset); + void set_interconnect_default_path_id(t_interconnect* interconnect, + const size_t& default_path_id); private: /* Internal data */ /* For regular bitstreams */ /* A look up for pb type to find bitstream source type */ @@ -68,6 +71,12 @@ class VprBitstreamAnnotation { std::map mode_select_bitstream_contents_; /* Offset to be applied to mode-select bitstream */ std::map mode_select_bitstream_offsets_; + + /* A look up for interconnect to find default path indices + * Note: this is different from the default path in bitstream setting which is the index + * of inputs in the context of the interconnect input string + */ + std::map interconnect_default_path_ids_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index 63a0b0430..3da3f3ae1 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -177,7 +177,9 @@ int link_arch(OpenfpgaContext& openfpga_ctx, /* Build bitstream annotation based on bitstream settings */ if (CMD_EXEC_FATAL_ERROR == annotate_bitstream_setting(openfpga_ctx.bitstream_setting(), g_vpr_ctx.device(), + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.mutable_vpr_bitstream_annotation())) { + return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 1fb2360e9..e90d73321 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -189,6 +189,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_clustering_annotation(), openfpga_ctx.vpr_placement_annotation(), + openfpga_ctx.vpr_bitstream_annotation(), verbose); VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index f0cfab7dd..d5241a451 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -129,6 +129,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, t_mode* physical_mode) { @@ -197,6 +198,12 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag } } + /* Overwrite the default path if defined in bitstream annotation */ + if ( (size_t(DEFAULT_PATH_ID) == mux_input_pin_id) + && (mux_input_pin_id != bitstream_annotation.interconnect_default_path_id(cur_interc)) ) { + mux_input_pin_id = bitstream_annotation.interconnect_default_path_id(cur_interc); + } + /* Generate bitstream depend on both technology and structure of this MUX */ std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, mux_input_pin_id); @@ -266,6 +273,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, const e_circuit_pb_port_type& pb_port_type, @@ -276,7 +284,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode); @@ -288,7 +296,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode); @@ -300,7 +308,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode); @@ -327,6 +335,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, t_mode* physical_mode) { @@ -348,7 +357,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, */ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode); @@ -367,13 +376,13 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, /* For each child_pb_graph_node input pins*/ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode); } @@ -534,6 +543,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, @@ -578,7 +588,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, pb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, + device_annotation, bitstream_annotation, border_side, physical_pb, child_pb, &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), @@ -623,7 +633,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, build_physical_block_interc_bitstream(bitstream_manager, pb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, + device_annotation, bitstream_annotation, physical_pb_graph_node, physical_pb, physical_mode); } @@ -644,6 +654,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const DeviceGrid& grids, const vtr::Point& grid_coord, const e_side& border_side) { @@ -692,7 +703,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, border_side, + device_annotation, bitstream_annotation, + border_side, PhysicalPb(), PhysicalPbId::INVALID(), lb_type->pb_graph_head, z); } else { @@ -707,7 +719,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, border_side, + device_annotation, bitstream_annotation, + border_side, phy_pb, top_pb_id, pb_graph_head, z); } } @@ -731,6 +744,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { VTR_LOGV(verbose, "Generating bitstream for core grids..."); @@ -753,7 +767,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, + place_annotation, bitstream_annotation, grids, grid_coord, NUM_SIDES); } } @@ -780,7 +794,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, + place_annotation, bitstream_annotation, grids, io_coordinate, io_side); } } diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index be2425c5a..9d2c3d010 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -14,6 +14,7 @@ #include "vpr_device_annotation.h" #include "vpr_clustering_annotation.h" #include "vpr_placement_annotation.h" +#include "vpr_bitstream_annotation.h" /******************************************************************** * Function declaration @@ -32,6 +33,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); } /* end namespace openfpga */ From 5976cc0a1ce3e1ae9f47d525239fbabbf5cfd01c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 15:54:18 -0600 Subject: [PATCH 166/352] [Test] Add test case for using bitstream setting to overload default paths for pb_type interconnection --- .../config/bitstream_annotation.xml | 3 ++ .../config/task.conf | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml create mode 100644 openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf diff --git a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml new file mode 100644 index 000000000..2bb8ec56d --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml @@ -0,0 +1,3 @@ + + + diff --git a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf new file mode 100644 index 000000000..769a2ed4a --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 1*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_bitstream_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v + +[SYNTHESIS_PARAM] +bench0_top = and2_pipelined +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= From 18eb5c9de9ff4c853c0275bf9ab43d694389b1ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 15:56:41 -0600 Subject: [PATCH 167/352] [Test] Deploy new test to CI --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index e5b0c2f42..f85fc8d59 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -11,7 +11,6 @@ echo -e "FPGA-Bitstream regression tests"; echo -e "Testing bitstream generation for an auto-sized device"; run-task fpga_bitstream/generate_bitstream/device_auto --debug --show_thread_logs - echo -e "Testing bitstream generation for an 48x48 FPGA device"; run-task fpga_bitstream/generate_bitstream/device_48x48 --debug --show_thread_logs @@ -23,3 +22,6 @@ run-task fpga_bitstream/load_external_architecture_bitstream --debug --show_thre echo -e "Testing repacker capability in identifying wire LUTs"; run-task fpga_bitstream/repack_wire_lut --debug --show_thread_logs + +echo -e "Testing overloading default paths for programmable interconnect when generating bitstream"; +run-task fpga_bitstream/overload_mux_default_path--debug --show_thread_logs From 578d81b67a518acefa091e0d759a5bfbeebe319d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 16:15:00 -0600 Subject: [PATCH 168/352] [Test] Patch task configuration file --- .../overload_mux_default_path/config/bitstream_annotation.xml | 2 +- .../fpga_bitstream/overload_mux_default_path/config/task.conf | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml index 2bb8ec56d..519a837ef 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml +++ b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml @@ -1,3 +1,3 @@ - + diff --git a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf index 769a2ed4a..70fe861c2 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/task.conf @@ -16,10 +16,11 @@ timeout_each_job = 1*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml openfpga_bitstream_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/overload_mux_default_path/config/bitstream_annotation.xml +openfpga_vpr_device_layout=2x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml From 64163edbe671dc1dc1252530ae2c4416d5fa0ff6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 16:15:25 -0600 Subject: [PATCH 169/352] [Script] Add a custom script to run OpenFPGA in a fixed device size using global tile clock and bitstream setting --- ..._bitstream_setting_example_script.openfpga | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga new file mode 100644 index 000000000..dabb0c6c6 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga @@ -0,0 +1,77 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Read OpenFPGA bitstream settings +read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 9b3dcc65bd6f42914bd4f5733cbe0abc059e1b45 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 16:37:21 -0600 Subject: [PATCH 170/352] [Doc] Add new bitstream setting syntex 'interconnect' to documentation --- .../manual/file_formats/bitstream_setting.rst | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index d5d4649b4..764bf0c87 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -6,19 +6,35 @@ Bitstream Setting (.xml) An example of bitstream settings is shown as follows. This can define a hard-coded bitstream for a reconfigurable resource in FPGA fabrics. +.. warning:: Bitstream setting is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream. + .. code-block:: xml + -.. option:: pb_type="" +pb_type-related Settings +^^^^^^^^^^^^^^^^^^^^^^^^ - The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example, ``pb_type="clb.fle[arithmetic].soft_adder.adder_lut4"`` +The following syntax are applicable to the XML definition tagged by ``pb_type`` in bitstream setting files. + +.. option:: name="" + + The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example, + + .. code-block:: xml + + pb_type="clb.fle[arithmetic].soft_adder.adder_lut4" .. option:: source="" - The source of the ``pb_type`` bitstream, which could be from a ``.eblif`` file. For example, ``source="eblif"``. + The source of the ``pb_type`` bitstream, which could be from a ``.eblif`` file. For example, + + .. code-block:: xml + + source="eblif" .. option:: content="" @@ -33,5 +49,25 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab Specify the offset to be applied when overloading the bitstream to a target. For example, a LUT may have a 16-bit bitstream. When ``offset=1``, bitstream overloading will skip the first bit and start from the second bit of the 16-bit bitstream. -.. warning:: Bitstream setting is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream. +Interconnection-related Settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following syntax are applicable to the XML definition tagged by ``interconnect`` in bitstream setting files. + +.. option:: name="" + + The ``interconnect`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example, + + .. code-block:: xml + + pb_type="clb.fle[arithmetic].mux1" + +.. option:: default_path="" + + The default path denotes an input name that is consistent with VPR's architecture description. For example, in VPR architecture, there is a mux defined as + + .. code-block:: xml + + + + The default path can be either ``iopad.inpad`` or ``ff.Q`` which corresponds to the first input and the second input respectively. From 2fa370d7d5ddb09b51e2eb2d8f07d316ae087135 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Apr 2021 17:15:14 -0600 Subject: [PATCH 171/352] [Test] Patch regression tests for fpga bitstream --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index f85fc8d59..db692c002 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -24,4 +24,4 @@ echo -e "Testing repacker capability in identifying wire LUTs"; run-task fpga_bitstream/repack_wire_lut --debug --show_thread_logs echo -e "Testing overloading default paths for programmable interconnect when generating bitstream"; -run-task fpga_bitstream/overload_mux_default_path--debug --show_thread_logs +run-task fpga_bitstream/overload_mux_default_path --debug --show_thread_logs From 96ce6b545f8c3404af3f19d5603af8fe0fd6c674 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 13:53:08 -0600 Subject: [PATCH 172/352] [Tool] Patch repack to consider design constraints for pins that are not equivalent --- .../src/repack_design_constraints.cpp | 22 +++++ .../src/repack_design_constraints.h | 18 ++++ openfpga/src/repack/repack.cpp | 90 +++++++++++++------ 3 files changed, 105 insertions(+), 25 deletions(-) diff --git a/libopenfpga/librepackdc/src/repack_design_constraints.cpp b/libopenfpga/librepackdc/src/repack_design_constraints.cpp index d19c1ba71..c32ad6bb3 100644 --- a/libopenfpga/librepackdc/src/repack_design_constraints.cpp +++ b/libopenfpga/librepackdc/src/repack_design_constraints.cpp @@ -50,6 +50,20 @@ std::string RepackDesignConstraints::net(const RepackDesignConstraintId& repack_ return repack_design_constraint_nets_[repack_design_constraint_id]; } +std::string RepackDesignConstraints::find_constrained_pin_net(const std::string& pb_type, + const openfpga::BasicPort& pin) const { + std::string constrained_net_name; + for (const RepackDesignConstraintId& design_constraint : design_constraints()) { + /* If found a constraint, record the net name */ + if ( (pb_type == repack_design_constraint_pb_types_[design_constraint]) + && (pin == repack_design_constraint_pins_[design_constraint])) { + constrained_net_name = repack_design_constraint_nets_[design_constraint]; + break; + } + } + return constrained_net_name; +} + bool RepackDesignConstraints::empty() const { return 0 == repack_design_constraint_ids_.size(); } @@ -106,3 +120,11 @@ void RepackDesignConstraints::set_net(const RepackDesignConstraintId& repack_des bool RepackDesignConstraints::valid_design_constraint_id(const RepackDesignConstraintId& design_constraint_id) const { return ( size_t(design_constraint_id) < repack_design_constraint_ids_.size() ) && ( design_constraint_id == repack_design_constraint_ids_[design_constraint_id] ); } + +bool RepackDesignConstraints::unconstrained_net(const std::string& net) const { + return net.empty(); +} + +bool RepackDesignConstraints::unmapped_net(const std::string& net) const { + return std::string(REPACK_DESIGN_CONSTRAINT_OPEN_NET) == net; +} diff --git a/libopenfpga/librepackdc/src/repack_design_constraints.h b/libopenfpga/librepackdc/src/repack_design_constraints.h index c32a0aca8..8c1ca6415 100644 --- a/libopenfpga/librepackdc/src/repack_design_constraints.h +++ b/libopenfpga/librepackdc/src/repack_design_constraints.h @@ -61,6 +61,10 @@ class RepackDesignConstraints { /* Get the net to be constrained */ std::string net(const RepackDesignConstraintId& repack_design_constraint_id) const; + /* Find a constrained net */ + std::string find_constrained_pin_net(const std::string& pb_type, + const openfpga::BasicPort& pin) const; + /* Check if there are any design constraints */ bool empty() const; @@ -86,6 +90,20 @@ class RepackDesignConstraints { public: /* Public invalidators/validators */ bool valid_design_constraint_id(const RepackDesignConstraintId& repack_design_constraint_id) const; + /* Show if the net has no constraints (free to map to any pin) + * This function is used to identify the net name returned by APIs: + * - find_constrained_pin_net() + * - net() + */ + bool unconstrained_net(const std::string& net) const; + + /* Show if the net is defined specifically not to map to any pin + * This function is used to identify the net name returned by APIs: + * - find_constrained_pin_net() + * - net() + */ + bool unmapped_net(const std::string& net) const; + private: /* Internal data */ /* Unique ids for each design constraint */ vtr::vector repack_design_constraint_ids_; diff --git a/openfpga/src/repack/repack.cpp b/openfpga/src/repack/repack.cpp index 3611909bb..5e25179a5 100644 --- a/openfpga/src/repack/repack.cpp +++ b/openfpga/src/repack/repack.cpp @@ -230,6 +230,38 @@ std::vector find_routed_pb_graph_pins_atom_net(const t_pb* pb, return sink_pb_pins; } +/*************************************************************************************** + * This function will find the actual routing traces of the demanded net + * There is a specific search space applied when searching the routing traces: + * - ONLY applicable to the pb_pin of top-level pb_graph_node + * - candidate can be limited to a set of pb pins + ***************************************************************************************/ +static +std::vector find_pb_route_by_atom_net(const t_pb* pb, + const t_pb_graph_pin* source_pb_pin, + const AtomNetId& atom_net_id) { + VTR_ASSERT(true == source_pb_pin->parent_node->is_root()); + + std::vector pb_route_indices; + + for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) { + /* Bypass unused pins */ + if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { + continue; + } + /* Get the driver pb pin id, it must be valid */ + if (atom_net_id != pb->pb_route.at(pin).atom_net_id) { + continue; + } + + if (source_pb_pin->port == pb->pb_route.at(pin).pb_graph_pin->port) { + pb_route_indices.push_back(pin); + } + } + + return pb_route_indices; +} + /*************************************************************************************** * This function will find the actual source_pb_pin that is mapped by packed in the pb route * As the inputs of clustered block may be renamed during routing, @@ -422,18 +454,7 @@ void add_lb_router_nets(LbRouter& lb_router, AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin]; /* Check if the net information is constrained or not */ - std::string constrained_net_name; - for (const RepackDesignConstraintId& design_constraint : design_constraints.design_constraints()) { - /* All the pin must have only 1 bit */ - VTR_ASSERT_SAFE(1 == design_constraints.pin(design_constraint).get_width()); - /* If found a constraint, record the net name */ - if ( (std::string(lb_type->pb_type->name) == design_constraints.pb_type(design_constraint)) - && (std::string(source_pb_pin->port->name) == design_constraints.pin(design_constraint).get_name()) - && (size_t(source_pb_pin->pin_number) == design_constraints.pin(design_constraint).get_lsb())) { - constrained_net_name = design_constraints.net(design_constraint); - break; - } - } + std::string constrained_net_name = design_constraints.find_constrained_pin_net(std::string(lb_type->pb_type->name), BasicPort(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number)); /* Find the constrained net mapped to this pin in clustering results */ AtomNetId constrained_atom_net_id = AtomNetId::INVALID(); @@ -443,16 +464,21 @@ void add_lb_router_nets(LbRouter& lb_router, * - if this is valid net name, find the net id from atom_netlist * and overwrite the atom net id to mapped */ - if (!constrained_net_name.empty()) { - if (std::string(REPACK_DESIGN_CONSTRAINT_OPEN_NET) != constrained_net_name) { - constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name); - if (false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)) { - VTR_LOG_WARN("Invalid net '%s' to be constrained! Will drop the constraint in repacking\n", - constrained_net_name.c_str()); - } + if ( (!design_constraints.unconstrained_net(constrained_net_name)) + && (!design_constraints.unmapped_net(constrained_net_name))) { + constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name); + if (false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)) { + VTR_LOG_WARN("Invalid net '%s' to be constrained! Will drop the constraint in repacking\n", + constrained_net_name.c_str()); + } else { + VTR_ASSERT_SAFE(false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)); + VTR_LOGV(verbose, + "Accept net '%s' to be constrained on pin '%s[%d]' during repacking\n", + constrained_net_name.c_str(), + source_pb_pin->port->name, + source_pb_pin->pin_number); } - } else { - VTR_ASSERT_SAFE(constrained_net_name.empty()); + } else if (design_constraints.unconstrained_net(constrained_net_name)) { constrained_atom_net_id = atom_net_id; } @@ -486,18 +512,35 @@ void add_lb_router_nets(LbRouter& lb_router, LbRRNodeId source_lb_rr_node = lb_rr_graph.find_node(LB_INTERMEDIATE, source_pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(source_lb_rr_node)); + /* Output verbose messages for debugging only */ + VTR_LOGV(verbose, + "Pb route for Net %s:\n", + atom_ctx.nlist.net_name(atom_net_id_to_route).c_str()); + /* As the pin remapping is allowed during routing, we should * - Find the routing traces from packing results which is mapped to the net * from the same port (as remapping is allowed for pins in the same port only) * - Find the source pb_graph_pin that drives the routing traces during packing * - Then we can find the sink nodes + * + * When there is a pin constraint applied. The routing trace + * - Find the routing traces from packing results which is mapped to the net + * with the same port constraints */ - std::vector pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route); + std::vector pb_route_indices; + if (design_constraints.unconstrained_net(constrained_net_name)) { + pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route); + } else { + VTR_ASSERT_SAFE(!design_constraints.unconstrained_net(constrained_net_name)); + pb_route_indices = find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id_to_route); + } /* It could happen that the constrained net is NOT used in this clb, we just skip it for routing * For example, a clkB net is never mapped to any ports in the pb that is clocked by clkA net * */ int pb_route_index; if (0 == pb_route_indices.size()) { + VTR_LOGV(verbose, + "Bypass routing due to no routing traces found\n"); continue; } else { VTR_ASSERT(1 == pb_route_indices.size()); @@ -512,9 +555,6 @@ void add_lb_router_nets(LbRouter& lb_router, VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size()); /* Output verbose messages for debugging only */ - VTR_LOGV(verbose, - "Pb route for Net %s:\n", - atom_ctx.nlist.net_name(atom_net_id_to_route).c_str()); VTR_LOGV(verbose, "Source node:\n\t%s -> %s\n", source_pb_pin->to_string().c_str(), From b203ef7bc27e3a92d8c5f4dbda87c39639fcaf0f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 14:03:51 -0600 Subject: [PATCH 173/352] [Benchmark] Add new benchmark 2-clock version of and2_latch as an essential test for multi-clock FPGAs --- .../and2_latch_2clock/and2_latch_2clock.v | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v b/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v new file mode 100644 index 000000000..a34cfdc91 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v @@ -0,0 +1,49 @@ +///////////////////////////////////////// +// Functionality: Two 2-input AND with clocked +// and combinational outputs +// Each of which are controlled by different clocks +// Author: Xifan Tang +//////////////////////////////////////// + +`timescale 1ns / 1ps + +module and2_latch_2clock( + a0, + b0, + clk0, + a1, + b1, + clk1, + c0, + d0, + c1, + d1); + +input wire clk0; + +input wire a0; +input wire b0; +output wire c0; +output reg d0; + +input wire clk1; + +input wire a1; +input wire b1; +output wire c1; +output reg d1; + + +assign c0 = a0 & b0; + +always @(posedge clk0) begin + d0 <= c0; +end + +assign c1 = a1 & b1; + +always @(posedge clk1) begin + d1 <= c1; +end + +endmodule From 8046b16c151cba318a6da4ec867e8003e0dd9194 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 14:04:34 -0600 Subject: [PATCH 174/352] [Test] Remove restrictions in the multi-clock test case and deploy new microbenchmarks for testing --- .../global_tile_4clock/config/task.conf | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_4clock/config/task.conf b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_4clock/config/task.conf index 275a32b57..e7cbcb5ab 100644 --- a/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_4clock/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_4clock/config/task.conf @@ -9,17 +9,11 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 20*60 -# Due to the limitation in ACE2 which cannot output .blif files -# with correct multi-clock assignments to .latch lines -# We have to use the vpr_blif flow where the .blif is modified -# based on yosys outputs with correct clock assignment! -# TODO: This limitation should be removed and we should use yosys_vpr flow!!! -fpga_flow=vpr_blif -#fpga_flow=yosys_vpr +fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga @@ -32,14 +26,12 @@ openfpga_pin_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_te arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTile4Clk_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter4bit_2clock/counter4bit_2clock.blif -#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter4bit_2clock/counter4bit_2clock.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter4bit_2clock/counter4bit_2clock.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v [SYNTHESIS_PARAM] bench0_top = counter4bit_2clock -bench0_act=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter4bit_2clock/counter4bit_2clock.act -bench0_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter4bit_2clock/counter4bit_2clock_post_yosys.v -bench0_chan_width = 300 +bench1_top = and2_latch_2clock [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 2e1cc5499d53719d6b899835175c2265ba7879e3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 14:14:54 -0600 Subject: [PATCH 175/352] [Doc] Add disclaimer for limitations when using repack pin constraints --- .../manual/file_formats/repack_design_constraints.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/file_formats/repack_design_constraints.rst b/docs/source/manual/file_formats/repack_design_constraints.rst index 5771123c2..56f40c310 100644 --- a/docs/source/manual/file_formats/repack_design_constraints.rst +++ b/docs/source/manual/file_formats/repack_design_constraints.rst @@ -3,6 +3,11 @@ Repack Design Constraints (.xml) -------------------------------- +.. warning:: For the best practice, current repack design constraints only support the net remapping between pins in the same port. Pin constraints are **NOT** allowed for two separated ports. + + - A legal pin constraint example: when there are two clock nets, ``clk0`` and ``clk1``, pin constraints are forced on two pins in a clock port ``clk[0:2]`` (e.g., ``clk[0] = clk0`` and ``clk[1] == clk1``). + - An **illegal** pin constraint example: when there are two clock nets, ``clk0`` and ``clk1``, pin constraints are forced on two clock ports ``clkA[0]`` and ``clkB[0]`` (e.g., ``clkA[0] = clk0`` and ``clkB[0] == clk1``). + An example of design constraints is shown as follows. .. code-block:: xml @@ -25,5 +30,5 @@ An example of design constraints is shown as follows. .. option:: net="" The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file. - + .. warning:: Design constraints is a feature for power-users. It may cause repack to fail. It is users's responsibility to ensure proper design constraints From 9d9840d9b7862a5aff22cbbd8e20a6e80ccf51b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 19:49:48 -0600 Subject: [PATCH 176/352] [Arch] Add architecture using multi-mode DFFs --- ...ain_dpram8K_dsp36_fracff_40nm_openfpga.xml | 308 +++++ ..._adder_chain_dpram8K_dsp36_fracff_40nm.xml | 1007 +++++++++++++++++ 2 files changed, 1315 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml create mode 100644 openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml new file mode 100644 index 000000000..d72b9176c --- /dev/null +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml new file mode 100644 index 000000000..002d11154 --- /dev/null +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml @@ -0,0 +1,1007 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + clb.clk clb.reset + clb.cin + clb.O[9:0] clb.I[19:0] + clb.cout clb.O[19:10] clb.I[39:20] + + + + + + + + + + + + + + + + + + + memory.clk + + memory.waddr[4:0] memory.raddr[4:0] memory.data_in[3:0] memory.wen memory.data_out[3:0] + memory.waddr[9:5] memory.raddr[9:5] memory.data_in[7:4] memory.ren memory.data_out[7:4] + + + + + + + + + + + + + + mult_36.b[0:9] mult_36.b[10:35] mult_36.out[36:71] + + mult_36.a[0:9] mult_36.a[10:35] mult_36.out[0:35] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3d615e1516ca52d7d79051fbbbb3f5d146254d5d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 19:50:07 -0600 Subject: [PATCH 177/352] [Script] Add yosys script supporting customize DFF/BRAM/DSP mapping --- .../ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys diff --git a/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys new file mode 100644 index 000000000..7244532e5 --- /dev/null +++ b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys @@ -0,0 +1,105 @@ +# Yosys synthesis script for ${TOP_MODULE} + +######################### +# Parse input files +######################### +# Read verilog files +${READ_VERILOG_FILE} +# Read technology library +read_verilog -lib -specify ${YOSYS_CELL_SIM_VERILOG} + +######################### +# Prepare for synthesis +######################### +# Identify top module from hierarchy +hierarchy -check -top ${TOP_MODULE} +# - Convert process blocks to AST +proc +# Flatten all the gates/primitives +flatten +# Identify tri-state buffers from 'z' signal in AST +# with follow-up optimizations to clean up AST +tribuf -logic +opt_expr +opt_clean +# demote inout ports to input or output port +# with follow-up optimizations to clean up AST +deminout +opt + +opt_expr +opt_clean +check +opt +wreduce -keepdc +peepopt +pmuxtree +opt_clean + +######################## +# Map multipliers +# Inspired from synth_xilinx.cc +######################### +# Avoid merging any registers into DSP, reserve memory port registers first +memory_dff +wreduce t:$mul +techmap -map +/mul2dsp.v -map ${YOSYS_DSP_MAP_VERILOG} ${YOSYS_DSP_MAP_PARAMETERS} +select a:mul2dsp +setattr -unset mul2dsp +opt_expr -fine +wreduce +select -clear +chtype -set $mul t:$__soft_mul# Extract arithmetic functions + +######################### +# Run coarse synthesis +######################### +# Run a tech map with default library +techmap +alumacc +share +opt +fsm +# Run a quick follow-up optimization to sweep out unused nets/signals +opt -fast +# Optimize any memory cells by merging share-able ports and collecting all the ports belonging to memorcy cells +memory -nomap +opt_clean + +######################### +# Map logics to BRAMs +######################### +memory_bram -rules ${YOSYS_BRAM_MAP_RULES} +techmap -map ${YOSYS_BRAM_MAP_VERILOG} +opt -fast -mux_undef -undriven -fine +memory_map +opt -undriven -fine + +######################### +# Map flip-flops +######################### +techmap -map ${YOSYS_DFF_MAP_VERILOG} +opt_expr -mux_undef +simplemap +opt_expr +opt_merge +opt_rmdff +opt_clean +opt + +######################### +# Map LUTs +######################### +abc -lut ${LUT_SIZE} + +######################### +# Check and show statisitics +######################### +hierarchy -check +stat + +######################### +# Output netlists +######################### +opt_clean -purge +write_blif ${OUTPUT_BLIF} From 8cbea6a2686899f226de0f53ccceb1e917571f14 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 19:50:51 -0600 Subject: [PATCH 178/352] [HDL] Add technology library for customizable DFF synthesis --- ...chain_dpram8K_dsp36_fracff_40nm_cell_sim.v | 127 ++++++++++++++++++ ..._chain_dpram8K_dsp36_fracff_40nm_dff_map.v | 18 +++ .../openfpga_yosys_techlib/openfpga_dff_sim.v | 2 +- 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v create mode 100644 openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v new file mode 100644 index 000000000..f075e8781 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v @@ -0,0 +1,127 @@ +//----------------------------- +// Dual-port RAM 1024x8 bit (8Kbit) +// Core logic +//----------------------------- +module dpram_1024x8_core ( + input wclk, + input wen, + input [0:9] waddr, + input [0:7] data_in, + input rclk, + input ren, + input [0:9] raddr, + output [0:7] data_out ); + + reg [0:7] ram[0:1023]; + reg [0:7] internal; + + assign data_out = internal; + + always @(posedge wclk) begin + if(wen) begin + ram[waddr] <= data_in; + end + end + + always @(posedge rclk) begin + if(ren) begin + internal <= ram[raddr]; + end + end + +endmodule + +//----------------------------- +// Dual-port RAM 1024x8 bit (8Kbit) wrapper +// where the read clock and write clock +// are combined to a unified clock +//----------------------------- +module dpram_1024x8 ( + input clk, + input wen, + input ren, + input [0:9] waddr, + input [0:9] raddr, + input [0:7] data_in, + output [0:7] data_out ); + + dpram_1024x8_core memory_0 ( + .wclk (clk), + .wen (wen), + .waddr (waddr), + .data_in (data_in), + .rclk (clk), + .ren (ren), + .raddr (raddr), + .data_out (data_out) ); + +endmodule + +//----------------------------- +// 36-bit multiplier +//----------------------------- +module mult_36( + input [0:35] A, + input [0:35] B, + output [0:71] Y +); + +assign Y = A * B; + +endmodule + +//----------------------------- +// Native D-type flip-flop +//----------------------------- +(* abc9_flop, lib_whitebox *) +module dff( + output reg Q, + input D, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C +); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + initial Q = INIT; + case(|IS_C_INVERTED) + 1'b0: + always @(posedge C) + Q <= D; + 1'b1: + always @(negedge C) + Q <= D; + endcase +endmodule + +//----------------------------- +// D-type flip-flop with asynchronous reset +//----------------------------- +(* abc9_flop, lib_whitebox *) +module dffr( + output reg Q, + input D, + input R, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C +); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + initial Q = INIT; + case(|IS_C_INVERTED) + 1'b0: + always @(posedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else + Q <= D; + 1'b1: + always @(negedge C or posedge R) + if (R == 1'b1) + Q <= 1'b0; + else + Q <= D; + endcase +endmodule + diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v new file mode 100644 index 000000000..822706642 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v @@ -0,0 +1,18 @@ +// Basic DFF +module \$_DFF_P_ (D, C, Q); + input D; + input C; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dff _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C)); +endmodule + +// Async reset +module \$_DFF_PP0_ (D, C, R, Q); + input D; + input C; + input R; + output Q; + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + dffr _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .R(R)); +endmodule diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v index 90926cef6..d4798a906 100644 --- a/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v @@ -93,4 +93,4 @@ module latchre ( if (S) Q <= 1'b1; else if (E && G) Q <= D; end -endmodule \ No newline at end of file +endmodule From 3a5c26c6a16bd14a040518222ac3099d50706d9d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 19:51:25 -0600 Subject: [PATCH 179/352] [Test] Update IWLS test by using new architecture and customize DFF techmap --- .../benchmark_sweep/iwls2005/config/task.conf | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf b/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf index 60eaeec4a..6db54bc7d 100644 --- a/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf +++ b/openfpga_flow/tasks/benchmark_sweep/iwls2005/config/task.conf @@ -17,10 +17,11 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml # Yosys script parameters -yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v @@ -30,48 +31,54 @@ yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINW vpr_route_chan_width=300 [ARCHITECTURES] -arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml [BENCHMARKS] # RTL netlists from IWLS 2005 benchmark release -# Comment out due to DFF synthesis problems +# Comment out it requires falling edge latches which are not supported yet #bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ac97_ctrl/rtl/*.v +# Comment out it requires synchronous reset which has not been supported yet #bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ethernet/rtl/*.v +# Comment out it requires set which has not been supported yet #bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/*.v +# Comment out it requires a active-low reset which has not been supported yet #bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/simple_spi/rtl/*.v # Comment out due to VHDL is not supported by Yosys without Verific #bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/steppermotordrive/rtl/*.vhd bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/tv80/rtl/*.v -# Comment out due to DFF synthesis problems +# Comment out it requires a active-low reset which has not been supported yet #bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/*.v # AES core has two top modules that can be tested: encryption and decryption # Synthesis is too long; skip it #bench7=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/*.v #bench8=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/aes_core/rtl/*.v #bench9=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/fpu/rtl/*.v -# Comment out due to DFF synthesis problems +# Comment out it requires set which has not been supported yet #bench10=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/pci/rtl/*.v +# Comment out it requires set which has not been supported yet #bench11=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/spi/rtl/*.v +# Comment out it requires a active-low reset which has not been supported yet #bench12=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/systemcaes/rtl/*.v bench13=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/*.v -# Comment out due to DFF synthesis problems -#bench14=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/*.v +bench14=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/wb_conmax/rtl/*.v ## DES has two versions: area-optimized and performance optimized -bench15=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/*.v -bench16=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/*.v -# Comment out due to DFF synthesis problems +# The DES has same top-level module name as systemcdes +# Currently openfpga flow has a bug which does not allow same top-level module name +#bench15=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/area_opt/rtl/*.v +#bench16=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/des/perf_opt/rtl/*.v +# Comment out it requires a active-low reset which has not been supported yet #bench17=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/i2c/rtl/*.v -# Comment out due to DFF synthesis problems +# Comment out it requires a active-low reset which has not been supported yet #bench18=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/sasc/rtl/*.v bench19=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/ss_pcm/rtl/*.v -# Comment out due to DFF synthesis problems +# Comment out it requires a active-low reset which has not been supported yet #bench20=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/systemcdes/rtl/*.v bench21=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/usb_phy/rtl/*.v -# Comment out due to DFF synthesis problems +# Comment out it requires a active-low reset which has not been supported yet #bench22=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/iwls2005/wb_dma/rtl/*.v [SYNTHESIS_PARAM] -bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys bench0_top = ac97_top bench1_top = eth_top bench2_top = mc_top From 62497549b6c0ebd35bda56decfccd847a2ac076a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 20:04:40 -0600 Subject: [PATCH 180/352] [HDL] Add multi-mode DFF module --- .../openfpga_cell_library/verilog/dff.v | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dff.v b/openfpga_flow/openfpga_cell_library/verilog/dff.v index a0548c54c..a82b88fae 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dff.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dff.v @@ -289,6 +289,34 @@ assign Q = q_reg; endmodule //End Of Module +//----------------------------------------------------- +// Function : A multi-functional D-type flip-flop with +// - asynchronous reset +// which can be switched between active-low and active hight +// - asynchronous set which can be switched +// which can be switched between active-low and active hight +//----------------------------------------------------- +module MULTIMODE_DFFSRQ ( + input SET, // Set input + input RST, // Reset input + input CK, // Clock Input + input D, // Data Input + output Q, // Q output + input [0:1] mode // mode-selection bits: bit0 for reset polarity; bit1 for set polarity +); + +wire post_set = mode ? ~SET : SET; +wire post_reset = mode ? ~RST : RST; + +DFFSRQ FF_CORE (.SET(post_set), + .RST(post_rst), + .CK(CK), + .D(D), + .Q(Q) + ); + +endmodule //End Of Module + //----------------------------------------------------- // Function : D-type flip-flop with // - asynchronous active high reset From adfea88be21b79613540feb31504c6f4337ac825 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 20:06:03 -0600 Subject: [PATCH 181/352] [HDL] Rename multi-mode DFF module --- openfpga_flow/openfpga_cell_library/verilog/dff.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dff.v b/openfpga_flow/openfpga_cell_library/verilog/dff.v index a82b88fae..a1d3e2407 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dff.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dff.v @@ -296,7 +296,7 @@ endmodule //End Of Module // - asynchronous set which can be switched // which can be switched between active-low and active hight //----------------------------------------------------- -module MULTIMODE_DFFSRQ ( +module MULTI_MODE_DFFSRQ ( input SET, // Set input input RST, // Reset input input CK, // Clock Input From ce6018e1235fcb29aebc0276b0d5f15e80d80778 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 21 Apr 2021 22:48:31 -0600 Subject: [PATCH 182/352] [Arch] Enriched DFF model to support active-low/high FFs --- ...ain_dpram8K_dsp36_fracff_40nm_openfpga.xml | 49 +++- ..._adder_chain_dpram8K_dsp36_fracff_40nm.xml | 226 +++++++++++++++++- 2 files changed, 258 insertions(+), 17 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml index d72b9176c..d1cf24921 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml @@ -139,15 +139,16 @@ - + - + + @@ -240,6 +241,9 @@ + + + @@ -257,7 +261,7 @@ - + @@ -266,11 +270,18 @@ - + - - + + + + + + + + + @@ -278,22 +289,36 @@ - + - - + + + + + + + + + - + - - + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml index 002d11154..db1b5bef4 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml @@ -147,7 +147,7 @@ - + @@ -157,7 +157,17 @@ - + + + + + + + + + + + @@ -168,6 +178,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -190,6 +230,7 @@ + @@ -198,12 +239,13 @@ + - clb.clk clb.reset + clb.clk clb.reset clb.set clb.cin clb.O[9:0] clb.I[19:0] clb.cout clb.O[19:10] clb.I[39:20] @@ -412,6 +454,7 @@ + @@ -423,6 +466,7 @@ + @@ -432,6 +476,7 @@ + @@ -456,13 +501,15 @@ - + + + @@ -491,6 +538,7 @@ + @@ -510,6 +558,7 @@ + @@ -517,6 +566,7 @@ + @@ -545,6 +595,7 @@ + @@ -592,6 +643,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -600,6 +702,7 @@ + @@ -612,6 +715,7 @@ + @@ -620,6 +724,7 @@ + @@ -660,6 +765,7 @@ + @@ -707,9 +813,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -746,13 +904,15 @@ - + + + @@ -782,6 +942,7 @@ + @@ -829,6 +990,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -837,6 +1049,7 @@ + @@ -848,6 +1061,7 @@ + @@ -871,6 +1085,8 @@ + + - From 272d1fffb70fb6a02c4eb4d27f28b9b6b2b4a338 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 13:30:46 -0600 Subject: [PATCH 199/352] [HDL] Add tech library for architecture using multi-mode 16-bit DSP blocks --- ..._nonLR_caravel_io_skywater130nm_cell_sim.v | 25 +++++++++++ ...6_nonLR_caravel_io_skywater130nm_dsp_map.v | 41 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_cell_sim.v create mode 100644 openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v diff --git a/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_cell_sim.v new file mode 100644 index 000000000..d455c79d0 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_cell_sim.v @@ -0,0 +1,25 @@ +//----------------------------- +// 8-bit multiplier +//----------------------------- +module mult_8( + input [0:7] A, + input [0:7] B, + output [0:15] Y +); + +assign Y = A * B; + +endmodule + +//----------------------------- +// 16-bit multiplier +//----------------------------- +module mult_16( + input [0:15] A, + input [0:15] B, + output [0:31] Y +); + +assign Y = A * B; + +endmodule diff --git a/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v b/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v new file mode 100644 index 000000000..035e6f7eb --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v @@ -0,0 +1,41 @@ +//----------------------------- +// 8-bit multiplier +//----------------------------- +module mult_8x8 ( + input [0:7] A, + input [0:7] B, + output [0:15] Y +); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + + mult_8 #() _TECHMAP_REPLACE_ ( + .A (A), + .B (B), + .Y (Y) ); + +endmodule + +//----------------------------- +// 16-bit multiplier +//----------------------------- +module mult_16x16 ( + input [0:15] A, + input [0:15] B, + output [0:31] Y +); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + + mult_16 #() _TECHMAP_REPLACE_ ( + .A (A), + .B (B), + .Y (Y) ); + +endmodule From 4f454abfde2ad6693be9dc422dee48a40fe9ed6a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 14:01:42 -0600 Subject: [PATCH 200/352] [Arch] Add a new architecture using fracturable 16-bit DSP blocks --- ...avel_io_skywater130nm_fdhd_cc_openfpga.xml | 295 ++++++ ...c_dsp16_nonLR_caravel_io_skywater130nm.xml | 962 ++++++++++++++++++ 2 files changed, 1257 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml create mode 100644 openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml diff --git a/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml new file mode 100644 index 000000000..7ce8c5c28 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml new file mode 100644 index 000000000..98bae4fa2 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml @@ -0,0 +1,962 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io_top.outpad io_top.inpad + + + + + + + + + + + + io_right.outpad io_right.inpad + + + + + + + + + + + + io_bottom.outpad io_bottom.inpad + + + + + + + + + + + + io_left.outpad io_left.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clb.clk clb.reset + clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I0 clb.I0i clb.I1 clb.I1i clb.I2 clb.I2i clb.I3 clb.I3i + clb.O[15:8] clb.I4 clb.I4i clb.I5 clb.I5i clb.I6 clb.I6i clb.I7 clb.I7i + clb.reg_out clb.sc_out clb.cout + + + + + + + + + + + + + + mult_16.a[0:5] mult_16.b[0:5] mult_16.out[0:10] + mult_16.a[6:7] mult_16.b[6:7] mult_16.out[11:15] + mult_16.a[8:13] mult_16.b[8:13] mult_16.out[16:26] + mult_16.a[14:15] mult_16.b[14:15] mult_16.out[27:31] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 148da80869b020aba0c73ccd6dbbc3ab982be15c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 14:53:29 -0600 Subject: [PATCH 201/352] [Tool] Add new syntax about physical_pb_port_rotate_offset to support fracturable heterogeneous block mapping between operating modes and physical modes --- .../src/pb_type_annotation.cpp | 40 +++++++++++--- .../libarchopenfpga/src/pb_type_annotation.h | 24 ++++++--- .../src/read_xml_pb_type_annotation.cpp | 25 +++++++++ .../src/write_xml_pb_type_annotation.cpp | 9 +++- openfpga/src/annotation/annotate_pb_graph.cpp | 26 +++++++++- openfpga/src/annotation/annotate_pb_types.cpp | 3 +- .../src/annotation/vpr_device_annotation.cpp | 52 +++++++++++++++++++ .../src/annotation/vpr_device_annotation.h | 15 +++++- openfpga/src/repack/repack.cpp | 6 +-- 9 files changed, 178 insertions(+), 22 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp index 9a369e742..1a1a7ea31 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp @@ -86,11 +86,11 @@ std::vector PbTypeAnnotation::port_names() const { return keys; } -std::map> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { - std::map>>::const_iterator it = operating_pb_type_ports_.find(port_name); +std::map> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { + std::map>>::const_iterator it = operating_pb_type_ports_.find(port_name); if (it == operating_pb_type_ports_.end()) { /* Return an empty port */ - return std::map>(); + return std::map>(); } return operating_pb_type_ports_.at(port_name); } @@ -169,25 +169,25 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) { void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port) { /* Give a warning if the operating_pb_port_name already exist */ - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); /* If not exist, initialize and set a default value */ if (it == operating_pb_type_ports_.end()) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0}; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0}; /* We can return early */ return; } /* If the physical port is not in the list, we create one and set a default value */ if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0}; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0}; } } void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, const int& physical_pin_initial_offset) { - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -210,7 +210,7 @@ void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operat void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, const int& physical_pin_rotate_offset) { - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -230,6 +230,30 @@ void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operati operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = physical_pin_rotate_offset; } +void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_port_rotate_offset) { + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + + if (it == operating_pb_type_ports_.end()) { + VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", + operating_pb_port_name.c_str()); + exit(1); + } + + if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), + physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), + operating_pb_port_name.c_str()); + exit(1); + } + + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] = physical_port_rotate_offset; +} + + void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name, const std::string& circuit_model_name) { std::map::const_iterator it = interconnect_circuit_model_names_.find(interc_name); diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h index 96383679d..2a0b8804e 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h @@ -49,7 +49,7 @@ class PbTypeAnnotation { float physical_pb_type_index_factor() const; int physical_pb_type_index_offset() const; std::vector port_names() const; - std::map> physical_pb_type_port(const std::string& port_name) const; + std::map> physical_pb_type_port(const std::string& port_name) const; std::vector interconnect_names() const; std::string interconnect_circuit_model_name(const std::string& interc_name) const; public: /* Public mutators */ @@ -73,6 +73,9 @@ class PbTypeAnnotation { void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, const int& physical_pin_rotate_offset); + void set_physical_port_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_port_rotate_offset); void add_interconnect_circuit_model_pair(const std::string& interc_name, const std::string& circuit_model_name); private: /* Internal data */ @@ -138,10 +141,10 @@ class PbTypeAnnotation { int physical_pb_type_index_offset_; /* Link from the pins under an operating pb_type to pairs of - * its physical pb_type and its pin initial & rotating offset - * - * Note that initial offset is the first element of the std::array - * Note that rotating offset is the second element of the std::array + * its physical pb_type and + * - its pin initial offset: the first element of the std::array + * - pin-level rotating offset: the second element of the std::array + * - port-level rotating offset: the third element of the std::array * * The offsets aim to align the pin indices for port of pb_type * between operating and physical modes, especially when an operating @@ -158,14 +161,21 @@ class PbTypeAnnotation { * physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0] * physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0] * - * For example, a rotating offset of 9 is used to map + * For example, a pin-level rotating offset of 9 is used to map + * operating pb_type mult_9x9[0].a[0] with a full path mult[frac].mult_9x9[0] + * operating pb_type mult_9x9[0].a[1] with a full path mult[frac].mult_9x9[1] + * to + * physical pb_type mult_36x36.a[0] with a full path mult[physical].mult_36x36[0] + * physical pb_type mult_36x36.a[9] with a full path mult[physical].mult_36x36[0] + * + * For example, a port-level rotating offset of 9 is used to map * operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0] * operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1] * to * physical pb_type mult_36x36.a[0:8] with a full path mult[physical].mult_36x36[0] * physical pb_type mult_36x36.a[9:17] with a full path mult[physical].mult_36x36[0] */ - std::map>> operating_pb_type_ports_; + std::map>> operating_pb_type_ports_; /* Link between the interconnects under this pb_type and circuit model names */ std::map interconnect_circuit_model_names_; diff --git a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp index 9831f6e23..f91dc99a8 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp @@ -114,6 +114,31 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port, std::stoi(rotate_offsets[iport])); } } + + /* We have an optional attribute: physical_mode_port_rotate_offset + * Split based on the number of physical pb_type ports that have been defined + */ + const std::string& physical_port_rotate_offset_attr = get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + + if (false == physical_port_rotate_offset_attr.empty()) { + /* Split the physical mode port attributes with space */ + openfpga::StringToken offset_tokenizer(physical_port_rotate_offset_attr); + const std::vector rotate_offsets = offset_tokenizer.split(); + + /* Error out if the offset does not match the port definition */ + if (physical_mode_ports.size() != rotate_offsets.size()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), + "Defined %lu physical mode ports but only %lu physical port rotate offset are defined! Expect size matching.\n", + physical_mode_ports.size(), rotate_offsets.size()); + } + + for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_port_rotate_offset(name_attr, + port_parser.port(), + std::stoi(rotate_offsets[iport])); + } + } } /******************************************************************** diff --git a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp index e9b36522c..b401f6ca8 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp @@ -144,7 +144,14 @@ void write_xml_pb_port_annotation(std::fstream& fp, physical_mode_pin_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[1]); } write_xml_attribute(fp, "physical_mode_pin_rotate_offset", physical_mode_pin_rotate_offset_attr.c_str()); - + std::string physical_mode_port_rotate_offset_attr; + for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) { + if (false == physical_mode_port_rotate_offset_attr.empty()) { + physical_mode_port_rotate_offset_attr += " "; + } + physical_mode_port_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[2]); + } + write_xml_attribute(fp, "physical_mode_port_rotate_offset", physical_mode_port_rotate_offset_attr.c_str()); fp << "/>" << "\n"; } diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 67a1baba8..bed7997cc 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -333,7 +333,7 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * by the pin rotate offset value * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port */ - int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port); + int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port) + vpr_device_annotation.physical_pb_port_offset(operating_pb_graph_pin->port, candidate_port); int init_offset = vpr_device_annotation.physical_pb_pin_initial_offset(operating_pb_graph_pin->port, candidate_port); const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, candidate_port); if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number @@ -463,6 +463,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no physical_pb_graph_node, vpr_device_annotation, verbose_output); } + /* Finish a port, accumulate the port-level offset affiliated to the port */ + if (0 == operating_pb_graph_node->num_input_pins[iport]) { + continue; + } + t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->input_pins[iport][0]); + for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + } } for (int iport = 0; iport < operating_pb_graph_node->num_output_ports; ++iport) { @@ -471,6 +479,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no physical_pb_graph_node, vpr_device_annotation, verbose_output); } + /* Finish a port, accumulate the port-level offset affiliated to the port */ + if (0 == operating_pb_graph_node->num_output_pins[iport]) { + continue; + } + t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->output_pins[iport][0]); + for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + } } for (int iport = 0; iport < operating_pb_graph_node->num_clock_ports; ++iport) { @@ -479,6 +495,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no physical_pb_graph_node, vpr_device_annotation, verbose_output); } + /* Finish a port, accumulate the port-level offset affiliated to the port */ + if (0 == operating_pb_graph_node->num_clock_pins[iport]) { + continue; + } + t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->clock_pins[iport][0]); + for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + } } } diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index 92a6f6560..e4b5f972c 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -211,7 +211,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, * if not found, we assume that the physical port is the same as the operating pb_port */ for (t_port* operating_pb_port : pb_type_ports(operating_pb_type)) { - std::map> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); + std::map> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); /* If not defined in the annotation, set the default pair: * rotate_offset is 0 by default! @@ -243,6 +243,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, physical_pb_port, expected_physical_pb_port.first); vpr_device_annotation.add_physical_pb_pin_initial_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[0]); vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[1]); + vpr_device_annotation.add_physical_pb_port_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[2]); } } diff --git a/openfpga/src/annotation/vpr_device_annotation.cpp b/openfpga/src/annotation/vpr_device_annotation.cpp index c2eed00ab..eef4fafbb 100644 --- a/openfpga/src/annotation/vpr_device_annotation.cpp +++ b/openfpga/src/annotation/vpr_device_annotation.cpp @@ -220,6 +220,21 @@ int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* operating_pb_port return physical_pb_pin_rotate_offsets_.at(operating_pb_port).at(physical_pb_port); } +int VprDeviceAnnotation::physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port); + if (it == physical_pb_port_rotate_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + if (0 == physical_pb_port_rotate_offsets_.at(operating_pb_port).count(physical_pb_port)) { + /* Default value is 0 */ + return 0; + } + return physical_pb_port_rotate_offsets_.at(operating_pb_port).at(physical_pb_port); +} + int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ @@ -235,6 +250,21 @@ int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port, return physical_pb_pin_offsets_.at(operating_pb_port).at(physical_pb_port); } +int VprDeviceAnnotation::physical_pb_port_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map>::const_iterator it = physical_pb_port_offsets_.find(operating_pb_port); + if (it == physical_pb_port_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + if (0 == physical_pb_port_offsets_.at(operating_pb_port).count(physical_pb_port)) { + /* Default value is 0 */ + return 0; + } + return physical_pb_port_offsets_.at(operating_pb_port).at(physical_pb_port); +} + t_pb_graph_pin* VprDeviceAnnotation::physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const { /* Ensure that the pb_type is in the list */ std::map::const_iterator it = physical_pb_graph_pins_.find(pb_graph_pin); @@ -478,6 +508,28 @@ void VprDeviceAnnotation::add_physical_pb_pin_initial_offset(t_port* operating_p physical_pb_pin_initial_offsets_[operating_pb_port][physical_pb_port] = offset; } +void VprDeviceAnnotation::add_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset) { + /* Warn any override attempt */ + std::map>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port); + if ( (it != physical_pb_port_rotate_offsets_.end()) + && (0 < physical_pb_port_rotate_offsets_[operating_pb_port].count(physical_pb_port)) ) { + VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' port rotate offset '%d'!\n", + operating_pb_port->name, offset); + } + + physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port] = offset; + /* We initialize the accumulated offset to 0 */ + physical_pb_port_offsets_[operating_pb_port][physical_pb_port] = 0; +} + + +void VprDeviceAnnotation::accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) { + physical_pb_port_offsets_[operating_pb_port][physical_pb_port] += physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port]; +} + void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port, const int& offset) { diff --git a/openfpga/src/annotation/vpr_device_annotation.h b/openfpga/src/annotation/vpr_device_annotation.h index b5afbda00..d1a0f8e99 100644 --- a/openfpga/src/annotation/vpr_device_annotation.h +++ b/openfpga/src/annotation/vpr_device_annotation.h @@ -67,6 +67,9 @@ class VprDeviceAnnotation { int physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port) const; + int physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; + /**This function returns an accumulated offset. Note that the * accumulated offset is NOT the pin rotate offset specified by users * It is an aggregation of the offset during pin pairing @@ -76,6 +79,8 @@ class VprDeviceAnnotation { */ int physical_pb_pin_offset(t_port* operating_pb_port, t_port* physical_pb_port) const; + int physical_pb_port_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; t_pb_graph_pin* physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const; CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const; CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const; @@ -106,6 +111,11 @@ class VprDeviceAnnotation { void add_physical_pb_pin_initial_offset(t_port* operating_pb_port, t_port* physical_pb_port, const int& offset); + void add_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); + void accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port); void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port, const int& offset); @@ -166,8 +176,11 @@ class VprDeviceAnnotation { std::map> physical_pb_ports_; std::map> physical_pb_pin_initial_offsets_; std::map> physical_pb_pin_rotate_offsets_; + std::map> physical_pb_port_rotate_offsets_; - /* Accumulated offsets for a physical pb_type port, just for internal usage */ + /* Accumulated offsets for a physical pb port, just for internal usage */ + std::map> physical_pb_port_offsets_; + /* Accumulated offsets for a physical pb_graph_pin, just for internal usage */ std::map> physical_pb_pin_offsets_; /* Pair a pb_port to its LSB and MSB of a physical pb_port diff --git a/openfpga/src/repack/repack.cpp b/openfpga/src/repack/repack.cpp index d6cb669bc..7538c675a 100644 --- a/openfpga/src/repack/repack.cpp +++ b/openfpga/src/repack/repack.cpp @@ -61,9 +61,9 @@ bool rec_direct_search_sink_pb_graph_pins(const t_pb_graph_pin* source_pb_pin, std::vector sink_pb_pins_to_search; /* Only support single-mode pb_type!!! */ - if (1 != source_pb_pin->parent_node->pb_type->num_modes) { - return false; - } + //if (1 != source_pb_pin->parent_node->pb_type->num_modes) { + // return false; + //} for (int iedge = 0; iedge < source_pb_pin->num_output_edges; ++iedge) { if (DIRECT_INTERC != source_pb_pin->output_edges[iedge]->interconnect->type) { From a3a98fa21d6365a67f57db0c1ef2ae11a9237df8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 14:56:10 -0600 Subject: [PATCH 202/352] [Arch] Bug fix for port name mismatching between openfpga cell library and architecture definition --- ...frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml index 7ce8c5c28..78978c2c7 100644 --- a/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml @@ -210,9 +210,9 @@ - - - + + + From 8b8096f3a860e655ebebd644f8673a3b5c2e11cc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 14:57:09 -0600 Subject: [PATCH 203/352] [HDL] Bug fix in HDL modeling of multi-mode 16-bit DSP block --- openfpga_flow/openfpga_cell_library/verilog/frac_mult_16x16.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_cell_library/verilog/frac_mult_16x16.v b/openfpga_flow/openfpga_cell_library/verilog/frac_mult_16x16.v index 7fedc711c..d73a1c7e1 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/frac_mult_16x16.v +++ b/openfpga_flow/openfpga_cell_library/verilog/frac_mult_16x16.v @@ -13,7 +13,7 @@ module frac_mult_16x16 ( output [0:31] out, input [0:0] mode); - reg [0:63] out_reg; + reg [0:31] out_reg; always @(mode, a, b) begin if (1'b1 == mode) begin From 80f98328df34411a6baaaf6b4ac57ee59a79c762 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 15:16:50 -0600 Subject: [PATCH 204/352] [Test] Update test settings for architecture with fracturable DSP blocks --- .../dsp/multi_mode_mult_16x16/config/task.conf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/tasks/fpga_verilog/dsp/multi_mode_mult_16x16/config/task.conf b/openfpga_flow/tasks/fpga_verilog/dsp/multi_mode_mult_16x16/config/task.conf index 0db63ef8b..b9e2c957b 100644 --- a/openfpga_flow/tasks/fpga_verilog/dsp/multi_mode_mult_16x16/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/dsp/multi_mode_mult_16x16/config/task.conf @@ -24,7 +24,7 @@ yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techli yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 # VPR parameter -openfpga_vpr_device_layout=3x2 +openfpga_vpr_device_layout=3x4 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml @@ -32,7 +32,8 @@ arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_sof [BENCHMARKS] bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v -bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_16/mac_16.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_12/mac_12.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_16/mac_16.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys @@ -40,7 +41,8 @@ bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosy bench0_top = mac_4 bench1_top = mac_8 -bench2_top = mac_16 +bench2_top = mac_12 +bench3_top = mac_16 [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 5adffad6023b8dad5bbbc75a9ab2de21b794e836 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 15:49:53 -0600 Subject: [PATCH 205/352] [Arch] Changes to the arch to avoid a bug where the rr_nodes at top side of a heterogenenous block have no fan-in!!! --- ...ac_dsp16_nonLR_caravel_io_skywater130nm.xml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml index 98bae4fa2..2d817e7cd 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml @@ -111,7 +111,7 @@ These clocks can be handled in back-end --> - + @@ -123,7 +123,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -217,10 +217,12 @@ - mult_16.a[0:5] mult_16.b[0:5] mult_16.out[0:10] - mult_16.a[6:7] mult_16.b[6:7] mult_16.out[11:15] - mult_16.a[8:13] mult_16.b[8:13] mult_16.out[16:26] - mult_16.a[14:15] mult_16.b[14:15] mult_16.out[27:31] + mult_16.a[0:2] mult_16.b[0:2] mult_16.out[0:5] + mult_16.a[3:5] mult_16.b[3:5] mult_16.out[6:10] + + mult_16.a[8:10] mult_16.b[8:10] mult_16.out[16:21] + mult_16.a[11:13] mult_16.b[11:13] mult_16.out[22:26] + mult_16.a[6:7] mult_16.b[6:7] mult_16.out[11:15] mult_16.a[14:15] mult_16.b[14:15] mult_16.out[27:31] @@ -239,7 +241,7 @@ - + From b7da22501c4ff35e56b6af623aceadaad967331f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 15:55:05 -0600 Subject: [PATCH 206/352] [Test] Deply new test to regression test --- openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 0033ad8ac..9168cbd1e 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -47,6 +47,9 @@ run-task fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs echo -e "Testing Verilog generation with heterogeneous fabric using 8-bit single-mode multipliers "; run-task fpga_verilog/dsp/single_mode_mult_8x8 --debug --show_thread_logs +echo -e "Testing Verilog generation with heterogeneous fabric using 16-bit multi-mode multipliers "; +run-task fpga_verilog/dsp/multi_mode_mult_16x16 --debug --show_thread_logs + echo -e "Testing Verilog generation with different I/O capacities on each side of an FPGA "; run-task fpga_verilog/io/multi_io_capacity --debug --show_thread_logs From 62dc5a3856035a009363f3862a0053b66908b72d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 24 Apr 2021 16:02:24 -0600 Subject: [PATCH 207/352] [Doc] Update documentation about the new syntax introduced for pin binding between operating modes and physical modes --- .../manual/arch_lang/annotate_vpr_arch.rst | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/source/manual/arch_lang/annotate_vpr_arch.rst b/docs/source/manual/arch_lang/annotate_vpr_arch.rst index 239d10dfb..f4767c938 100644 --- a/docs/source/manual/arch_lang/annotate_vpr_arch.rst +++ b/docs/source/manual/arch_lang/annotate_vpr_arch.rst @@ -223,7 +223,9 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de .. note:: A ```` parent XML node is required for the interconnect-to-circuit bindings whose interconnects are defined under the ``pb_type`` in VPR architecture description. .. option:: + physical_mode_pin_initial_offset="" + physical_mode_pin_rotate_offset=""/> + physical_mode_port_rotate_offset=""/> Link a port of an operating ``pb_type`` to a port of a physical ``pb_type`` @@ -233,7 +235,6 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de .. note:: Users can define multiple ports. For example: ``physical_mode_pin="a[0:1] b[2:2]"``. When multiple ports are used, the ``physical_mode_pin_initial_offset`` and ``physical_mode_pin_rotate_offset`` should also be adapt. For example: ``physical_mode_pin_rotate_offset="1 0"``) - - ``physical_mode_pin_initial_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when part of port of operating mode is mapped to a port in physical ``pb_type``. When ``physical_mode_pin_initial_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. .. note:: A quick example to understand the initial offset @@ -249,7 +250,24 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de .. note:: If not defined, the default value of ``physical_mode_pin_initial_offset`` is set to ``0``. - - ``physical_mode_pin_rotate_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. + - ``physical_mode_pin_rotate_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset, **each time a pin in the operating mode is binded to a pin in the physical mode**. + + .. note:: A quick example to understand the rotate offset + For example, a rotating offset of 9 is used to map + + - operating pb_type ``mult_9x9[0].a[0]`` with a full path ``mult[frac].mult_9x9[0]`` + - operating pb_type ``mult_9x9[1].a[1]`` with a full path ``mult[frac].mult_9x9[1]`` + + to + + - physical pb_type ``mult_36x36.a[0]`` with a full path ``mult[physical].mult_36x36[0]`` + - physical pb_type ``mult_36x36.a[9]`` with a full path ``mult[physical].mult_36x36[0]`` + + .. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``. + + .. warning:: The result of using ``physical_mode_pin_rotate_offset`` is fundementally different than ``physical_mode_port_rotate_offset``!!! Please read the examples carefully and pick the one fitting your needs. + + - ``physical_mode_port_rotate_offset=""`` aims to align the port indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_port_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset, **only when all the pins of a port in the operating mode is binded to all the pins of a port in the physical mode**. .. note:: A quick example to understand the rotate offset For example, a rotating offset of 9 is used to map @@ -262,7 +280,8 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de - physical pb_type ``mult_36x36.a[0:8]`` with a full path ``mult[physical].mult_36x36[0]`` - physical pb_type ``mult_36x36.a[9:17]`` with a full path ``mult[physical].mult_36x36[0]`` - .. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``. + .. note:: If not defined, the default value of ``physical_mode_port_rotate_offset`` is set to ``0``. + .. note:: It is highly recommended that only one physical mode is defined for a multi-mode configurable block. Try not to use nested physical mode definition. This will ease the debugging and lead to clean XML description. From 94c575fa7406aec832788b8c315551714eb912c1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 18:12:12 -0600 Subject: [PATCH 208/352] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 36 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b465fdee4..dc13788d2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,12 +10,21 @@ assignees: '' **Describe the bug** A clear and concise description of what the bug is. +Which part of OpenFPGA is buggy +- [ ] Documentation +- [ ] OpenFPGA flow +- [ ] FPGA-Verilog +- [ ] FPGA-Bitstream +- [ ] FPGA-SDC +- [ ] FPGA-SPICE +- [ ] VPR +- [ ] Yosys + **To Reproduce** Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error +1. Clone OpenFPGA repository and checkout commit id: +2. Execute OpenFPGA task or your own example: +3. See error **Expected behavior** A clear and concise description of what you expected to happen. @@ -24,9 +33,22 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Enviornment (please complete the following information):** - - OS: [e.g. CentOs, Ubuntu] - - Compiler [e.g. gcc, clang] - - Version [e.g. Github commit id] + - OS: + - [ ] CentOS 7 + - [ ] Ubuntu 18.04 + - [ ] Others. If so, please specify: + - Compiler + - [ ] gcc-5 + - [ ] gcc-6 + - [ ] gcc-7 + - [ ] gcc-8 + - [ ] gcc-9 + - [ ] clang-6 + - [ ] clang-8 + - [ ] Others. If so, please specify: + - Version + - [ ] Current master + - [ ] Others. If so, please specify Github commit id: **Additional context** Add any other context about the problem here. From 386dbf8c1a66ddd4d1e6f7b978ce59d2c17d4cc4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 18:30:48 -0600 Subject: [PATCH 209/352] Update pull_request_template.md --- .../pull_request_template.md | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index d1c458c04..8bec074e4 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -1,33 +1,35 @@ ---- -name: Pull request -about: Push a change to this project ---- +> ### Motivate of the pull request +> - [ ] To address an existing issue. If so, please provide a link to the issue: +> - [ ] Breaking new feature. If so, please describe details in the description part. -### Motivate of the pull request -- [ ] To address an existing issue. If so, please provide a link to the issue. -- [ ] Breaking new feature. If so, please decribe details in the description part. +> ### Describe the technical details +> #### What is currently done? (Provide issue link if applicable) +> ** Please provide a list of limitations if not specified in any issue ** +> - [ ] +> - [ ] +> +> #### What does this pull request change? +> ** Please provide a list of highlights of your changes. ** +> - [ ]
+> - [ ] -### Describe the technical details -- What is currently done? (Provide issue link if applicable) -- What does this pull request change? +> ### Which part of the code base require a change +> **In general, modification on existing submodules are not acceptable. You should push changes to upstream.** +> - [ ] VPR +> - [ ] Tileable routing architecture generator +> - [ ] OpenFPGA libraries +> - [ ] FPGA-Verilog +> - [ ] FPGA-Bitstream +> - [ ] FPGA-SDC +> - [ ] FPGA-SPICE +> - [ ] Flow scripts +> - [ ] Architecture library +> - [ ] Cell library +> - [ ] Documentation +> - [ ] Regression tests +> - [ ] Continous Integration (CI) scripts -### Which part of the code base require a change -**In general, modification on existing submodules are not acceptable. You should push changes to upstream.** -- [ ] VPR -- [ ] OpenFPGA libraries -- [ ] FPGA-Verilog -- [ ] FPGA-Bitstream -- [ ] FPGA-SDC -- [ ] FPGA-SPICE -- [ ] Flow scripts -- [ ] Architecture library -- [ ] Cell library +> ### Impact of the pull request -### Checklist of the pull request -- [ ] Require code changes. -- [ ] Require new tests to be added -- [ ] Require an update on documentation - -### Impact of the pull request -- [ ] Require a change on Quality of Results (QoR) -- [ ] Break back-compatibility. If so, please list who may be influenced. +> - [ ] Require a change on Quality of Results (QoR) +> - [ ] Break back-compatibility. If so, please list who may be influenced. From 4b8dab09134db788151f7b6c44b8630762afdd6d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 20:51:29 -0600 Subject: [PATCH 210/352] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 47 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dc13788d2..7c4465cb3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,16 +9,16 @@ assignees: '' **Describe the bug** A clear and concise description of what the bug is. - -Which part of OpenFPGA is buggy -- [ ] Documentation -- [ ] OpenFPGA flow -- [ ] FPGA-Verilog -- [ ] FPGA-Bitstream -- [ ] FPGA-SDC -- [ ] FPGA-SPICE -- [ ] VPR -- [ ] Yosys + + + + + + + + + + **To Reproduce** Steps to reproduce the behavior: @@ -33,22 +33,23 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Enviornment (please complete the following information):** + - OS: - - [ ] CentOS 7 - - [ ] Ubuntu 18.04 - - [ ] Others. If so, please specify: + + + - Compiler - - [ ] gcc-5 - - [ ] gcc-6 - - [ ] gcc-7 - - [ ] gcc-8 - - [ ] gcc-9 - - [ ] clang-6 - - [ ] clang-8 - - [ ] Others. If so, please specify: + + + + + + + + - Version - - [ ] Current master - - [ ] Others. If so, please specify Github commit id: + + **Additional context** Add any other context about the problem here. From 83167b6b61097bb44d1d08a7fb12e441686a71f3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 22:06:13 -0600 Subject: [PATCH 211/352] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7c4465cb3..d7543b878 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -38,7 +38,7 @@ If applicable, add screenshots to help explain your problem. - - Compiler + - Compiler: @@ -47,7 +47,7 @@ If applicable, add screenshots to help explain your problem. - - Version + - Version: From a8b2966709e13774cca8edc3cbd758588fcafc3d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 22:08:17 -0600 Subject: [PATCH 212/352] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d7543b878..b5ef99630 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,8 +7,8 @@ assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. +> **Describe the bug** +> A clear and concise description of what the bug is. @@ -20,25 +20,25 @@ A clear and concise description of what the bug is. -**To Reproduce** -Steps to reproduce the behavior: -1. Clone OpenFPGA repository and checkout commit id: -2. Execute OpenFPGA task or your own example: -3. See error +> **To Reproduce** +> Steps to reproduce the behavior: +> 1. Clone OpenFPGA repository and checkout commit id: +> 2. Execute OpenFPGA task or your own example: +> 3. See error -**Expected behavior** -A clear and concise description of what you expected to happen. +> **Expected behavior** +> A clear and concise description of what you expected to happen. -**Screenshots** -If applicable, add screenshots to help explain your problem. +> **Screenshots** +> If applicable, add screenshots to help explain your problem. -**Enviornment (please complete the following information):** +> **Enviornment (please complete the following information):** - - OS: +> - OS: - - Compiler: +> - Compiler: @@ -47,9 +47,9 @@ If applicable, add screenshots to help explain your problem. - - Version: +> - Version: -**Additional context** -Add any other context about the problem here. +> **Additional context** +> Add any other context about the problem here. From deb9f4a9f78990276a5a4051304c5d43a6284b79 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 25 Apr 2021 22:11:34 -0600 Subject: [PATCH 213/352] Update pull_request_template.md --- .../pull_request_template.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 8bec074e4..f1b1063fd 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -4,17 +4,21 @@ > ### Describe the technical details > #### What is currently done? (Provide issue link if applicable) -> ** Please provide a list of limitations if not specified in any issue ** -> - [ ] -> - [ ] +> +> +> +> +> > > #### What does this pull request change? -> ** Please provide a list of highlights of your changes. ** -> - [ ]
-> - [ ] +> +> +> +> +> > ### Which part of the code base require a change -> **In general, modification on existing submodules are not acceptable. You should push changes to upstream.** +> > - [ ] VPR > - [ ] Tileable routing architecture generator > - [ ] OpenFPGA libraries From 880624e69925defd9a858d0e88de352379d071b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 11:48:02 -0600 Subject: [PATCH 214/352] [Tool] Update comments in tileable rr_graph generator to be easier to be understood --- .../tileable_rr_graph_gsb.cpp | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 2cef83e5c..524a856da 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -821,9 +821,8 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, opin_grid_side[1] = NUM_SIDES; } - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - /* Local variables inside this for loop */ SideManager side_manager(side); size_t ix; size_t iy; @@ -832,42 +831,34 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, enum e_side ipin_rr_node_grid_side; switch (side) { - case TOP: /* TOP = 0 */ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ + case TOP: + /* Consider the routing channel that is connected to the left side of the switch block */ chan_side = LEFT; - /* Build the connection block: ipin and ipin_grid_side */ - /* BOTTOM side INPUT Pins of Grid[x][y+1] */ + /* The input pins of the routing channel come from the bottom side of Grid[x][y+1] */ ix = rr_gsb.get_sb_x(); iy = rr_gsb.get_sb_y() + 1; ipin_rr_node_grid_side = BOTTOM; break; - case RIGHT: /* RIGHT = 1 */ - /* For the bording, we should take special care */ - /* Check if TOP side chan width is 0 or not */ + case RIGHT: + /* Consider the routing channel that is connected to the top side of the switch block */ chan_side = TOP; - /* Build the connection block: ipin and ipin_grid_side */ - /* LEFT side INPUT Pins of Grid[x+1][y+1] */ + /* The input pins of the routing channel come from the left side of Grid[x+1][y+1] */ ix = rr_gsb.get_sb_x() + 1; iy = rr_gsb.get_sb_y() + 1; ipin_rr_node_grid_side = LEFT; break; - case BOTTOM: /* BOTTOM = 2*/ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ + case BOTTOM: + /* Consider the routing channel that is connected to the left side of the switch block */ chan_side = LEFT; - /* Build the connection block: ipin and ipin_grid_side */ - /* TOP side INPUT Pins of Grid[x][y] */ + /* The input pins of the routing channel come from the top side of Grid[x][y] */ ix = rr_gsb.get_sb_x(); iy = rr_gsb.get_sb_y(); ipin_rr_node_grid_side = TOP; break; - case LEFT: /* LEFT = 3 */ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ + case LEFT: + /* Consider the routing channel that is connected to the top side of the switch block */ chan_side = TOP; - /* Build the connection block: ipin and ipin_grid_side */ - /* RIGHT side INPUT Pins of Grid[x][y+1] */ + /* The input pins of the routing channel come from the right side of Grid[x][y+1] */ ix = rr_gsb.get_sb_x(); iy = rr_gsb.get_sb_y() + 1; ipin_rr_node_grid_side = RIGHT; From cbd7105083fc0b2a3c2ad26da98263041c6fc350 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 11:57:17 -0600 Subject: [PATCH 215/352] [Tool] Add illustrative comments to tileable rr_graph generator --- .../tileable_rr_graph_gsb.cpp | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 524a856da..12b9dd0b8 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -821,7 +821,34 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, opin_grid_side[1] = NUM_SIDES; } - /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block */ + /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * | Grid[x][y+1] | + * | BOTTOM side | + * +-----------------------+ + * | + * v + * +-----------------------+ + * | TOP side | + * | X- Connection Block | + * | BOTTOM side | + * +-----------------------+ + * ^ + * | + * +-----------------------+ + * | TOP side | + * | Grid[x][y] | + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * ---------------+ +---------------------- ... ---------------------+ +---------------- + * Grid[x][y+1] |->| Y- Connection Block Y- Connection Block |<-| Grid[x+1][y+1] + * RIGHT side | | LEFT side ... RIGHT side | | LEFT side + * --------------+ +---------------------- ... ---------------------+ +---------------- + * + */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); size_t ix; From 6e87b8875bc90f4ee69cb44ba3b9e768ac8ad3aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 11:59:25 -0600 Subject: [PATCH 216/352] [Arch] Patch the pin location of frac dsp16 to appear on the top side of a height=2 block --- ...r_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml index 2d817e7cd..fd23eb91e 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm.xml @@ -219,10 +219,10 @@ mult_16.a[0:2] mult_16.b[0:2] mult_16.out[0:5] mult_16.a[3:5] mult_16.b[3:5] mult_16.out[6:10] - + mult_16.a[6:7] mult_16.b[6:7] mult_16.out[11:15] mult_16.a[8:10] mult_16.b[8:10] mult_16.out[16:21] mult_16.a[11:13] mult_16.b[11:13] mult_16.out[22:26] - mult_16.a[6:7] mult_16.b[6:7] mult_16.out[11:15] mult_16.a[14:15] mult_16.b[14:15] mult_16.out[27:31] + mult_16.a[14:15] mult_16.b[14:15] mult_16.out[27:31] From 7d4c5e3cd145e52e93ca93d7a879774b630fce49 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 12:00:57 -0600 Subject: [PATCH 217/352] [Arch] Patch pin location of dsp8 to be evenly placed on the right side of a height=2 block --- ...register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml index fea61541c..187a3e474 100644 --- a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml @@ -210,7 +210,8 @@ - mult_8.a[0:5] mult_8.b[0:5] mult_8.out[0:10] + mult_8.a[0:2] mult_8.b[0:2] mult_8.out[0:5] + mult_8.a[3:5] mult_8.b[3:5] mult_8.out[6:10] mult_8.a[6:7] mult_8.b[6:7] mult_8.out[11:15] From 05f08c2f2510bb1378dc8cf3350538aa24d6ae8d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 12:05:37 -0600 Subject: [PATCH 218/352] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 64 +++++++++++++++++--------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d1c458c04..f1b1063fd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,33 +1,39 @@ ---- -name: Pull request -about: Push a change to this project ---- +> ### Motivate of the pull request +> - [ ] To address an existing issue. If so, please provide a link to the issue: +> - [ ] Breaking new feature. If so, please describe details in the description part. -### Motivate of the pull request -- [ ] To address an existing issue. If so, please provide a link to the issue. -- [ ] Breaking new feature. If so, please decribe details in the description part. +> ### Describe the technical details +> #### What is currently done? (Provide issue link if applicable) +> +> +> +> +> +> +> #### What does this pull request change? +> +> +> +> +> -### Describe the technical details -- What is currently done? (Provide issue link if applicable) -- What does this pull request change? +> ### Which part of the code base require a change +> +> - [ ] VPR +> - [ ] Tileable routing architecture generator +> - [ ] OpenFPGA libraries +> - [ ] FPGA-Verilog +> - [ ] FPGA-Bitstream +> - [ ] FPGA-SDC +> - [ ] FPGA-SPICE +> - [ ] Flow scripts +> - [ ] Architecture library +> - [ ] Cell library +> - [ ] Documentation +> - [ ] Regression tests +> - [ ] Continous Integration (CI) scripts -### Which part of the code base require a change -**In general, modification on existing submodules are not acceptable. You should push changes to upstream.** -- [ ] VPR -- [ ] OpenFPGA libraries -- [ ] FPGA-Verilog -- [ ] FPGA-Bitstream -- [ ] FPGA-SDC -- [ ] FPGA-SPICE -- [ ] Flow scripts -- [ ] Architecture library -- [ ] Cell library +> ### Impact of the pull request -### Checklist of the pull request -- [ ] Require code changes. -- [ ] Require new tests to be added -- [ ] Require an update on documentation - -### Impact of the pull request -- [ ] Require a change on Quality of Results (QoR) -- [ ] Break back-compatibility. If so, please list who may be influenced. +> - [ ] Require a change on Quality of Results (QoR) +> - [ ] Break back-compatibility. If so, please list who may be influenced. From 8c007c7c4987ba6c7dfb28ade2936cf46ad83f51 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 16:28:10 -0600 Subject: [PATCH 219/352] [Arch] Add a new example architecture where a DSP block occupies a 2x2 grid --- ...c_dsp16_nonLR_caravel_io_skywater130nm.xml | 966 ++++++++++++++++++ 1 file changed, 966 insertions(+) create mode 100644 openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_wide_frac_dsp16_nonLR_caravel_io_skywater130nm.xml diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_wide_frac_dsp16_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_wide_frac_dsp16_nonLR_caravel_io_skywater130nm.xml new file mode 100644 index 000000000..4e30607e2 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_wide_frac_dsp16_nonLR_caravel_io_skywater130nm.xml @@ -0,0 +1,966 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io_top.outpad io_top.inpad + + + + + + + + + + + + io_right.outpad io_right.inpad + + + + + + + + + + + + io_bottom.outpad io_bottom.inpad + + + + + + + + + + + + io_left.outpad io_left.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clb.clk clb.reset + clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I0 clb.I0i clb.I1 clb.I1i clb.I2 clb.I2i clb.I3 clb.I3i + clb.O[15:8] clb.I4 clb.I4i clb.I5 clb.I5i clb.I6 clb.I6i clb.I7 clb.I7i + clb.reg_out clb.sc_out clb.cout + + + + + + + + + + + + + + mult_16.a[0:1] mult_16.b[0:1] mult_16.out[0:3] + mult_16.a[2:3] mult_16.b[2:3] mult_16.out[4:7] + mult_16.a[4:5] mult_16.b[4:5] mult_16.out[8:11] + mult_16.a[6:7] mult_16.b[6:7] mult_16.out[12:15] + mult_16.a[8:9] mult_16.b[8:9] mult_16.out[16:19] + mult_16.a[10:11] mult_16.b[10:11] mult_16.out[20:23] + mult_16.a[12:13] mult_16.b[12:13] mult_16.out[24:27] + mult_16.a[14:15] mult_16.b[14:15] mult_16.out[28:31] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6291871faf9874777eaffd25910b64d74277a4ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 16:28:43 -0600 Subject: [PATCH 220/352] [Test] Added a test for the example architecture with 2x2 DSP blocks --- .../config/task.conf | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_verilog/dsp/wide_multi_mode_mult_16x16/config/task.conf diff --git a/openfpga_flow/tasks/fpga_verilog/dsp/wide_multi_mode_mult_16x16/config/task.conf b/openfpga_flow/tasks/fpga_verilog/dsp/wide_multi_mode_mult_16x16/config/task.conf new file mode 100644 index 000000000..3923047e8 --- /dev/null +++ b/openfpga_flow/tasks/fpga_verilog/dsp/wide_multi_mode_mult_16x16/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_frac_dsp16_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_cell_sim.v +yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_frac_dsp16_nonLR_caravel_io_skywater130nm_dsp_map.v +yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +# VPR parameter +openfpga_vpr_device_layout=4x4 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_wide_frac_dsp16_nonLR_caravel_io_skywater130nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_16/mac_16.v + +[SYNTHESIS_PARAM] +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = mac_8 +bench1_top = mac_16 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= From 1d5e926d9e805fafa011a4b2838f6373f0123e90 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 16:29:54 -0600 Subject: [PATCH 221/352] [Test] Deploy new test to CI --- openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 9168cbd1e..8f64816de 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -50,6 +50,9 @@ run-task fpga_verilog/dsp/single_mode_mult_8x8 --debug --show_thread_logs echo -e "Testing Verilog generation with heterogeneous fabric using 16-bit multi-mode multipliers "; run-task fpga_verilog/dsp/multi_mode_mult_16x16 --debug --show_thread_logs +echo -e "Testing Verilog generation with heterogeneous fabric using multi-width 16-bit multi-mode multipliers "; +run-task fpga_verilog/dsp/wide_multi_mode_mult_16x16 --debug --show_thread_logs + echo -e "Testing Verilog generation with different I/O capacities on each side of an FPGA "; run-task fpga_verilog/io/multi_io_capacity --debug --show_thread_logs From 33c12c8f0ef801d5e3cdc9a2981367334ddfd1e9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Apr 2021 20:51:54 -0600 Subject: [PATCH 222/352] Update CMakeLists.txt --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b2fa1fb..a6a055ba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,6 @@ else () "-D__USE_FIXED_PROTOTYPES__" "-ansi" "-Wshadow" - "-Wcast-allign" "-Wno-write-strings" "-D_POSIX_SOURCE" "-Wall" #Most warnings, typically good From 43c1e052efcf28f8ceeb7b5f5e58dfa5ae677652 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:30:16 -0600 Subject: [PATCH 223/352] [Tool] Add a writer to output I/O mapping information to XML files --- openfpga/src/base/io_map.cpp | 54 +++++++ openfpga/src/base/io_map.h | 59 +++++++ openfpga/src/base/io_map_fwd.h | 23 +++ openfpga/src/base/openfpga_bitstream.cpp | 44 ++++++ openfpga/src/base/openfpga_bitstream.h | 3 + .../src/base/openfpga_bitstream_command.cpp | 38 +++++ .../fpga_bitstream/build_io_mapping_info.cpp | 144 +++++++++++++++++ .../fpga_bitstream/build_io_mapping_info.h | 33 ++++ .../fpga_bitstream/write_xml_io_mapping.cpp | 145 ++++++++++++++++++ .../src/fpga_bitstream/write_xml_io_mapping.h | 25 +++ 10 files changed, 568 insertions(+) create mode 100644 openfpga/src/base/io_map.cpp create mode 100644 openfpga/src/base/io_map.h create mode 100644 openfpga/src/base/io_map_fwd.h create mode 100644 openfpga/src/fpga_bitstream/build_io_mapping_info.cpp create mode 100644 openfpga/src/fpga_bitstream/build_io_mapping_info.h create mode 100644 openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp create mode 100644 openfpga/src/fpga_bitstream/write_xml_io_mapping.h diff --git a/openfpga/src/base/io_map.cpp b/openfpga/src/base/io_map.cpp new file mode 100644 index 000000000..3012c4285 --- /dev/null +++ b/openfpga/src/base/io_map.cpp @@ -0,0 +1,54 @@ +/****************************************************************************** + * Memember functions for data structure IoMap + ******************************************************************************/ +#include "vtr_assert.h" + +#include "io_map.h" + +/* begin namespace openfpga */ +namespace openfpga { + +IoMap::io_map_range IoMap::io_map() const { + return vtr::make_range(io_map_ids_.begin(), io_map_ids_.end()); +} + +BasicPort IoMap::io_port(IoMapId io_map_id) const { + VTR_ASSERT(valid_io_map_id(io_map_id)); + return io_ports_[io_map_id]; +} + +BasicPort IoMap::io_net(IoMapId io_map_id) const { + VTR_ASSERT(valid_io_map_id(io_map_id)); + return mapped_nets_[io_map_id]; +} + +bool IoMap::is_io_output(IoMapId io_map_id) const { + VTR_ASSERT(valid_io_map_id(io_map_id)); + return IoMap::IO_MAP_DIR_OUTPUT == io_directionality_[io_map_id]; +} + +bool IoMap::is_io_input(IoMapId io_map_id) const { + VTR_ASSERT(valid_io_map_id(io_map_id)); + return IoMap::IO_MAP_DIR_INPUT == io_directionality_[io_map_id]; +} + +IoMapId IoMap::create_io_mapping(const BasicPort& port, + const BasicPort& net, + IoMap::e_direction dir) { + /* Create a new id */ + IoMapId io_map_id = IoMapId(io_map_ids_.size()); + io_map_ids_.push_back(io_map_id); + + /* Allocate related attributes */ + io_ports_.push_back(port); + mapped_nets_.push_back(net); + io_directionality_.push_back(dir); + + return io_map_id; +} + +bool IoMap::valid_io_map_id(IoMapId io_map_id) const { + return (size_t(io_map_id) < io_map_ids_.size()) && (io_map_id == io_map_ids_[io_map_id]); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/base/io_map.h b/openfpga/src/base/io_map.h new file mode 100644 index 000000000..5bc378000 --- /dev/null +++ b/openfpga/src/base/io_map.h @@ -0,0 +1,59 @@ +#ifndef IO_MAP_H +#define IO_MAP_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include "vtr_vector.h" +#include "openfpga_port.h" +#include "io_map_fwd.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This is a data structure storing io mapping information + * - the net-to-I/O mapping + * - each I/O directionality + *******************************************************************/ +class IoMap { + public: /* Types and ranges */ + enum e_direction { + IO_MAP_DIR_INPUT, + IO_MAP_DIR_OUTPUT, + NUM_IO_MAP_DIR_TYPES + }; + typedef vtr::vector::const_iterator io_map_iterator; + typedef vtr::Range io_map_range; + public: /* Public aggregators */ + /* Find all io mapping */ + io_map_range io_map() const; + + /* Get the port of the io that is mapped */ + BasicPort io_port(IoMapId io_map_id) const; + + /* Get the net of the io that is mapped to */ + BasicPort io_net(IoMapId io_map_id) const; + + /* Query on if an io is configured as an input */ + bool is_io_input(IoMapId io_map_id) const; + + /* Query on if an io is configured as an output */ + bool is_io_output(IoMapId io_map_id) const; + public: /* Public mutators */ + /* Create a new I/O mapping */ + IoMapId create_io_mapping(const BasicPort& port, + const BasicPort& net, + e_direction dir); + public: /* Public validators/invalidators */ + bool valid_io_map_id(IoMapId io_map_id) const; + private: /* Internal Data */ + vtr::vector io_map_ids_; + vtr::vector io_ports_; + vtr::vector mapped_nets_; + vtr::vector io_directionality_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/openfpga/src/base/io_map_fwd.h b/openfpga/src/base/io_map_fwd.h new file mode 100644 index 000000000..0de3e99c1 --- /dev/null +++ b/openfpga/src/base/io_map_fwd.h @@ -0,0 +1,23 @@ +/************************************************** + * This file includes only declarations for + * the data structures for IoMap + * Please refer to io_map.h for more details + *************************************************/ +#ifndef IO_MAP_FWD_H +#define IO_MAP_FWD_H + +#include "vtr_strong_id.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/* Strong Ids */ +struct io_map_id_tag; + +typedef vtr::StrongId IoMapId; + +class IoMap; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index c32e9ae87..c35017ba8 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -15,10 +15,14 @@ #include "read_xml_arch_bitstream.h" #include "write_xml_arch_bitstream.h" +#include "openfpga_naming.h" + #include "build_device_bitstream.h" #include "write_text_fabric_bitstream.h" #include "write_xml_fabric_bitstream.h" #include "build_fabric_bitstream.h" +#include "build_io_mapping_info.h" +#include "write_xml_io_mapping.h" #include "openfpga_bitstream.h" /* Include global variables of VPR */ @@ -121,4 +125,44 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, return status; } +/******************************************************************** + * A wrapper function to call the write_io_mapping() in FPGA bitstream + *******************************************************************/ +int write_io_mapping(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_verbose = cmd.option("verbose"); + CommandOptionId opt_file = cmd.option("file"); + + /* Write fabric bitstream if required */ + int status = CMD_EXEC_SUCCESS; + + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + + std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file)); + + /* Create directories */ + create_directory(src_dir_path); + + /* Create a module as the top-level fabric, and add it to the module manager */ + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = openfpga_ctx.module_graph().find_module(top_module_name); + VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); + + IoMap io_map = build_fpga_io_mapping_info(openfpga_ctx.module_graph(), + top_module, + g_vpr_ctx.atom(), + g_vpr_ctx.placement(), + openfpga_ctx.io_location_map(), + openfpga_ctx.vpr_netlist_annotation(), + std::string(), + std::string()); + + status = write_io_mapping_to_xml_file(io_map, + cmd_context.option_value(cmd, opt_file), + cmd_context.option_enable(cmd, opt_verbose)); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream.h b/openfpga/src/base/openfpga_bitstream.h index c210d6bab..2e438d56b 100644 --- a/openfpga/src/base/openfpga_bitstream.h +++ b/openfpga/src/base/openfpga_bitstream.h @@ -24,6 +24,9 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_io_mapping(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 6b7397a1c..3599bcac5 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -131,6 +131,36 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_io_mapping"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the io mapping information"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command 'fabric_bitstream' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O mapping information to a file"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_io_mapping); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + /******************************************************************** * Top-level function to add all the commands related to FPGA-Bitstream *******************************************************************/ @@ -172,6 +202,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell& shell) { std::vector cmd_dependency_write_fabric_bitstream; cmd_dependency_write_fabric_bitstream.push_back(shell_cmd_build_fabric_bitstream_id); add_openfpga_write_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream); + + /******************************** + * Command 'write_io_mapping' + */ + /* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */ + std::vector cmd_dependency_write_io_mapping; + cmd_dependency_write_io_mapping.push_back(shell_cmd_build_fabric_id); + add_openfpga_write_io_mapping_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_io_mapping); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp new file mode 100644 index 000000000..76fbda9a2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp @@ -0,0 +1,144 @@ +/******************************************************************** + * This file includes functions that build io mapping information + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from archopenfpga library */ +#include "openfpga_naming.h" + +#include "module_manager_utils.h" +#include "build_io_mapping_info.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function + * - builds the net-to-I/O mapping + * - identifies each I/O directionality + * - return a database containing the above information + * + * TODO: This function duplicates codes from + * function: print_verilog_testbench_connect_fpga_ios() in + * source file: verilog_testbench_utils.cpp + * Should consider how to merge the codes and share same builder function + *******************************************************************/ +IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, + const ModuleId& top_module, + const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix) { + IoMap io_map; + + /* Only mappable i/o ports can be considered */ + std::vector module_io_ports; + for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) { + /* Only care mappable I/O */ + if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + continue; + } + module_io_ports.push_back(gpio_port_id); + } + } + + /* Type mapping between VPR block and Module port */ + std::map atom_block_type_to_module_port_type; + atom_block_type_to_module_port_type[AtomBlockType::INPAD] = ModuleManager::MODULE_GPIN_PORT; + atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = ModuleManager::MODULE_GPOUT_PORT; + + /* Type mapping between VPR block and io mapping direction */ + std::map atom_block_type_to_io_map_direction; + atom_block_type_to_io_map_direction[AtomBlockType::INPAD] = IoMap::IO_MAP_DIR_INPUT; + atom_block_type_to_io_map_direction[AtomBlockType::OUTPAD] = IoMap::IO_MAP_DIR_OUTPUT; + + for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { + /* Bypass non-I/O atom blocks ! */ + if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) + && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + continue; + } + + /* If there is a GPIO port, use it directly + * Otherwise, should find a GPIN for INPAD + * or should find a GPOUT for OUTPAD + */ + std::pair mapped_module_io_info = std::make_pair(ModulePortId::INVALID(), -1); + for (const ModulePortId& module_io_port_id : module_io_ports) { + const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id); + + /* Find the index of the mapped GPIO in top-level FPGA fabric */ + size_t temp_io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.z, + module_io_port.get_name()); + + /* Bypass invalid index (not mapped to this GPIO port) */ + if (size_t(-1) == temp_io_index) { + continue; + } + + /* If the port is an GPIO port, just use it */ + if (ModuleManager::MODULE_GPIO_PORT == module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + break; + } + + /* If this is an INPAD, we can use an GPIN port (if available) */ + if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(atom_blk)] == module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + break; + } + } + + /* We must find a valid one */ + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, mapped_module_io_info.first)); + VTR_ASSERT(size_t(-1) != mapped_module_io_info.second); + + /* Ensure that IO index is in range */ + BasicPort module_mapped_io_port = module_manager.module_port(top_module, mapped_module_io_info.first); + size_t io_index = mapped_module_io_info.second; + + /* Set the port pin index */ + VTR_ASSERT(io_index < module_mapped_io_port.get_width()); + module_mapped_io_port.set_width(io_index, io_index); + + /* The block may be renamed as it contains special characters which violate Verilog syntax */ + std::string block_name = atom_ctx.nlist.block_name(atom_blk); + if (true == netlist_annotation.is_block_renamed(atom_blk)) { + block_name = netlist_annotation.block_name(atom_blk); + } + + /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 + * In addition, the input and output ports may have different postfix in naming + * due to verification context! Here, we give full customization on naming + */ + BasicPort benchmark_io_port; + if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { + benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix)); + benchmark_io_port.set_width(1); + } else { + VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); + benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix)); + benchmark_io_port.set_width(1); + } + + io_map.create_io_mapping(module_mapped_io_port, + benchmark_io_port, + atom_block_type_to_io_map_direction[atom_ctx.nlist.block_type(atom_blk)]); + } + + return io_map; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.h b/openfpga/src/fpga_bitstream/build_io_mapping_info.h new file mode 100644 index 000000000..615fafdd8 --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.h @@ -0,0 +1,33 @@ +#ifndef BUILD_IO_MAPPING_INFO_H +#define BUILD_IO_MAPPING_INFO_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "module_manager.h" +#include "vpr_context.h" +#include "io_location_map.h" +#include "io_map.h" +#include "vpr_netlist_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, + const ModuleId& top_module, + const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp new file mode 100644 index 000000000..b9c63ddc2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp @@ -0,0 +1,145 @@ +/******************************************************************** + * This file includes functions that output io mapping information + * to files in XML format + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_digest.h" + +/* Headers from archopenfpga library */ +#include "openfpga_naming.h" + +#include "openfpga_version.h" + +#include "build_io_mapping_info.h" +#include "write_xml_io_mapping.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function write header information to an I/O mapping file + *******************************************************************/ +static +void write_io_mapping_xml_file_head(std::fstream& fp) { + valid_file_stream(fp); + + auto end = std::chrono::system_clock::now(); + std::time_t end_time = std::chrono::system_clock::to_time_t(end); + + fp << "" << std::endl; + fp << std::endl; +} + +/******************************************************************** + * Write an io mapping pair to an XML file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_io_mapping_pair_to_xml_file(std::fstream& fp, + const IoMap& io_map, + const IoMapId& io_map_id, + int xml_hierarchy_depth) { + if (false == valid_file_stream(fp)) { + return 1; + } + + write_tab_to_file(fp, xml_hierarchy_depth); + + BasicPort io_port = io_map.io_port(io_map_id); + fp << "\n"; + + return 0; +} + +/******************************************************************** + * Write the io mapping information to an XML file + * Notes: + * - This file is designed for users to learn + * - what nets are mapped to each I/O is mapped, io[0] -> netA + * - what directionality is applied to each I/O, io[0] -> input + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +int write_io_mapping_to_xml_file(const IoMap& io_map, + const std::string& fname, + const bool& verbose) { + /* Ensure that we have a valid file name */ + if (true == fname.empty()) { + VTR_LOG_ERROR("Received empty file name to output io_mapping!\n\tPlease specify a valid file name.\n"); + return 1; + } + + std::string timer_message = std::string("Write I/O mapping into xml file '") + fname + std::string("'"); + vtr::ScopedStartFinishTimer timer(timer_message); + + /* Create the file stream */ + std::fstream fp; + fp.open(fname, std::fstream::out | std::fstream::trunc); + + check_file_stream(fname.c_str(), fp); + + /* Write XML head */ + write_io_mapping_xml_file_head(fp); + + int xml_hierarchy_depth = 0; + fp << "\n"; + + /* Output fabric bitstream to the file */ + int status = 0; + int io_map_cnt = 0; + for (const auto& io_map_id : io_map.io_map()) { + status = write_io_mapping_pair_to_xml_file(fp, + io_map, io_map_id, + xml_hierarchy_depth + 1); + io_map_cnt++; + if (1 == status) { + break; + } + } + + /* Print an end to the file here */ + fp << "\n"; + + VTR_LOGV(verbose, + "Outputted %d I/O mapping to file '%s'\n", + io_map, + fname.c_str()); + + /* Close file handler */ + fp.close(); + + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.h b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h new file mode 100644 index 000000000..330106141 --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h @@ -0,0 +1,25 @@ +#ifndef WRITE_XML_IO_MAPPING_H +#define WRITE_XML_IO_MAPPING_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "vpr_context.h" +#include "io_map.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int write_io_mapping_to_xml_file(const IoMap& io_map, + const std::string& fname, + const bool& verbose); + +} /* end namespace openfpga */ + +#endif From c5d36757c6bfcfb53ba03984d3caf6f077b6346b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:39:57 -0600 Subject: [PATCH 224/352] [Tool] Fix typo in io mapping writing --- openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp index b9c63ddc2..61f977e7e 100644 --- a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp @@ -66,13 +66,13 @@ int write_io_mapping_pair_to_xml_file(std::fstream& fp, fp << "name=\"" << io_port.get_name().c_str() << "[" << io_port.get_lsb() << ":" << io_port.get_msb() << "]" << "\""; VTR_ASSERT(1 == io_map.io_net(io_map_id).get_width()); - fp << "net=\"" << io_map.io_net(io_map_id).get_name().c_str() << "\""; + fp << " net=\"" << io_map.io_net(io_map_id).get_name().c_str() << "\""; if (io_map.is_io_input(io_map_id)) { - fp << "dir=\"" << "input" << "\""; + fp << " dir=\"" << "input" << "\""; } else { VTR_ASSERT_SAFE(io_map.is_io_output(io_map_id)); - fp << "dir=\"" << "output" << "\""; + fp << " dir=\"" << "output" << "\""; } fp << "/>\n"; From f9fd444b8694c897e96b89bb678866a6b8a312c7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:40:26 -0600 Subject: [PATCH 225/352] [Script] Add an write I/O mapping example script for openfpga shell --- .../write_io_mapping_example_script.openfpga | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga new file mode 100644 index 000000000..62735f8bd --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga @@ -0,0 +1,38 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --absorb_buffer_luts off + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enabled frame view creation to save runtime and memory +# Note that this is turned on when bitstream generation +# is the ONLY purpose of the flow!!! +build_fabric --compress_routing --frame_view #--verbose + +# Write I/O net mapping information +write_io_mapping --file io_mapping.xml --verbose + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From b8ced5377f3d6bb03070c8af95a632dcabe679ce Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:41:15 -0600 Subject: [PATCH 226/352] [Test] Add a test case for i/o mapping writer --- .../write_io_mapping/config/task.conf | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf diff --git a/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf new file mode 100644 index 000000000..a61ec038b --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf @@ -0,0 +1,32 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] From 6cb4d7d720182fa6fb4b1340bb725abc22664a76 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:41:38 -0600 Subject: [PATCH 227/352] [Test] Add the new test to regressiont test --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index db692c002..1f1eac786 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -25,3 +25,6 @@ run-task fpga_bitstream/repack_wire_lut --debug --show_thread_logs echo -e "Testing overloading default paths for programmable interconnect when generating bitstream"; run-task fpga_bitstream/overload_mux_default_path --debug --show_thread_logs + +echo -e "Testing outputting I/O mapping result to file"; +run-task fpga_bitstream/write_io_mapping --debug --show_thread_logs From 1bae59dc6a8bdfde8fabbe75b2547c02930cd7f4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 14:54:57 -0600 Subject: [PATCH 228/352] [Doc] Update documentation for the write_io_mapping command --- docs/source/manual/file_formats/index.rst | 2 ++ .../manual/file_formats/io_mapping_file.rst | 33 +++++++++++++++++++ .../fpga_bitstream_commands.rst | 16 +++++++++ 3 files changed, 51 insertions(+) create mode 100644 docs/source/manual/file_formats/io_mapping_file.rst diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst index f02218cd3..d1a77e2d0 100644 --- a/docs/source/manual/file_formats/index.rst +++ b/docs/source/manual/file_formats/index.rst @@ -21,3 +21,5 @@ OpenFPGA widely uses XML format for interchangable files bitstream_setting fabric_key + + io_mapping_file diff --git a/docs/source/manual/file_formats/io_mapping_file.rst b/docs/source/manual/file_formats/io_mapping_file.rst new file mode 100644 index 000000000..722f477f6 --- /dev/null +++ b/docs/source/manual/file_formats/io_mapping_file.rst @@ -0,0 +1,33 @@ +.. _file_format_io_mapping_file: + +I/O Mapping File (.xml) +----------------------- + +The I/O mapping file aims to show + +- What nets have been mapped to each I/O +- What is the directionality of each mapped I/O + +An example of design constraints is shown as follows. + +.. code-block:: xml + + + + + + + +.. option:: name="" + + The pin name of the FPGA fabric which has been mapped, which should be a valid pin defined in OpenFPGA architecture description. + + .. note:: You should be find the exact pin in the top-level module of FPGA fabric if you output the Verilog netlists. + +.. option:: net="" + + The net name which is actually mapped to a pin, which should be consistent with net definition in your ``.blif`` file. + +.. option:: dir="" + + The direction of an I/O, which can be either ``input`` or ``output``. diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index d2461b5ef..fbe10e033 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -72,3 +72,19 @@ write_fabric_bitstream .. option:: --verbose Show verbose log + +write_io_mapping +~~~~~~~~~~~~~~~~ + + Output the I/O mapping information to a file + + .. option:: --file or -f + + Specify the file name where the I/O mapping will be outputted to. + See file formats in :ref:`file_format_io_mapping_file`. + + .. option:: --verbose + + Show verbose log + + From 8728fd9561daa39968555ffc1c50e5ee827892aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 15:06:07 -0600 Subject: [PATCH 229/352] [Tool] Typo fix to resolve clang errors --- openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp index 61f977e7e..5b3f383b1 100644 --- a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp @@ -133,7 +133,7 @@ int write_io_mapping_to_xml_file(const IoMap& io_map, VTR_LOGV(verbose, "Outputted %d I/O mapping to file '%s'\n", - io_map, + io_map_cnt, fname.c_str()); /* Close file handler */ From 1d498bb29665881f821ec9a4885a72ef520833a3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 15:26:52 -0600 Subject: [PATCH 230/352] [Benchmark] Add a scalable micro benchmark fifo --- .../micro_benchmark/fifo/rtl/fifo.v | 97 +++++++++++++++++++ .../fifo/rtl/sync_dual_port_ram.v | 35 +++++++ 2 files changed, 132 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v new file mode 100644 index 000000000..af1bc6921 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v @@ -0,0 +1,97 @@ +// FIFO buffer implemented with synchronous dual-port block ram +// Reference: +// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/ +module fifo + #( parameter ADDRESS_WIDTH = 12, // number of words in ram + DATA_WIDTH = 8 // number of bits in word + ) + + // IO ports + ( + input wire clk, reset, + input wire read, write, + input wire [DATA_WIDTH-1:0] write_data, + output wire empty, full, + output wire [DATA_WIDTH-1:0] read_data + ); + + // internal signal declarations + reg [ADDRESS_WIDTH-1:0] write_address_reg, write_address_next, write_address_after; + reg [ADDRESS_WIDTH-1:0] read_address_reg, read_address_next, read_address_after; + reg full_reg, empty_reg, full_next, empty_next; + wire write_en; + + // write enable is asserted when write input is asserted and FIFO isn't full + assign write_en = write & ~full_reg; + + // instantiate synchronous block ram + sync_dual_port_ram #(.ADDRESS_WIDTH(ADDRESS_WIDTH), .DATA_WIDTH(DATA_WIDTH)) ram + (.clk(clk), .write_en(write_en), .write_address(write_address_reg), + .read_address(read_address_reg), .write_data_in(write_data), + .write_data_out(), .read_data_out(read_data)); + + // register for address pointers, full/empty status + always @(posedge clk, posedge reset) + if (reset) + begin + write_address_reg <= 0; + read_address_reg <= 0; + full_reg <= 1'b0; + empty_reg <= 1'b1; + end + else + begin + write_address_reg <= write_address_next; + read_address_reg <= read_address_next; + full_reg <= full_next; + empty_reg <= empty_next; + end + + // next-state logic for address index values after read/write operations + always @* + begin + write_address_after = write_address_reg + 1; + read_address_after = read_address_reg + 1; + end + + // next-state logic for address pointers + always @* + begin + // defaults + write_address_next = write_address_reg; + read_address_next = read_address_reg; + full_next = full_reg; + empty_next = empty_reg; + + // if read input asserted and FIFO isn't empty + if(read && ~empty_reg && ~write) + begin + read_address_next = read_address_after; // read address moves forward + full_next = 1'b0; // FIFO isn't full if a read occured + + if (read_address_after == write_address_reg) // if read address caught up with write address, + empty_next = 1'b1; // FIFO is empty + end + + // if write input asserted and FIFO isn't full + else if(write && ~full_reg && ~read) + begin + write_address_next = write_address_after; // write address moves forward + empty_next = 1'b0; // FIFO isn't empty if write occured + + if (write_address_after == read_address_reg) // if write address caught up with read address + full_next = 1'b1; // FIFO is full + end + + // if write and read are asserted + else if(write && read) + begin + write_address_next = write_address_after; // write address moves forward + read_address_next = read_address_after; // read address moves forward + end + end + + // assign full/empty status to output ports + assign full = full_reg; + assign empty = empty_reg; +endmodule \ No newline at end of file diff --git a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v new file mode 100644 index 000000000..5914129e4 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v @@ -0,0 +1,35 @@ +// Synchronous dual-port block ram +// Reference: +// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/ +module sync_dual_port_ram + #( parameter ADDRESS_WIDTH = 12, // number of words in ram + DATA_WIDTH = 8 // number of bits in word + ) + + // IO ports + ( + input wire clk, // clk for synchronous read/write + input wire write_en, // signal to enable synchronous write + input wire [ADDRESS_WIDTH-1:0] read_address, write_address, // inputs for dual port addresses + input wire [DATA_WIDTH-1:0] write_data_in, // input for data to write to ram + output wire [DATA_WIDTH-1:0] read_data_out, write_data_out // outputs for dual data ports + ); + + // internal signal declarations + reg [DATA_WIDTH-1:0] ram [2**ADDRESS_WIDTH-1:0]; // ADDRESS_WIDTH x DATA_WIDTH RAM declaration + reg [ADDRESS_WIDTH-1:0] read_address_reg, write_address_reg; // dual port address declarations + + // synchronous write and address update + always @(posedge clk) + begin + if (write_en) // if write enabled + ram[write_address] <= write_data_in; // write data to ram and write_address + + read_address_reg <= read_address; // store read_address to reg + write_address_reg <= write_address; // store write_address to reg + end + + // assignments for two data out ports + assign read_data_out = ram[read_address_reg]; + assign write_data_out = ram[write_address_reg]; +endmodule \ No newline at end of file From 0f8aaae2bcc95dabc62e242a18b055929f8ceb57 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 19:54:34 -0600 Subject: [PATCH 231/352] [Arch] Patch architecture using 16kbit dual port RAM --- ...c_N10_adder_chain_mem16K_40nm_openfpga.xml | 20 ++-- .../k6_frac_N10_adder_chain_mem16K_40nm.xml | 86 +++++++++-------- ...c_N10_tileable_adder_chain_mem16K_40nm.xml | 86 +++++++++-------- ..._tileable_adder_chain_wide_mem16K_40nm.xml | 93 ++++++++++--------- 4 files changed, 156 insertions(+), 129 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml index 5259e5e03..19064e7b6 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml @@ -194,17 +194,17 @@ - + - - - + + + - - + + @@ -222,6 +222,12 @@ + + + + + + @@ -267,7 +273,7 @@ - + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml index 796369e64..e60a26611 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml @@ -118,14 +118,14 @@ - + - + @@ -135,7 +135,7 @@ - + @@ -180,15 +180,21 @@ - - - + + + - + - + + memory.clk + + memory.wen memory.waddr[0:3] memory.raddr[0:3] memory.data_in[0:2] memory.data_out[0:2] + memory.ren memory.waddr[4:7] memory.raddr[4:7] memory.data_in[3:5] memory.data_out[3:5] + memory.waddr[8:11] memory.raddr[8:11] memory.data_in[6:7] memory.data_out[6:7] + @@ -682,57 +688,57 @@ - - - + + + - + - - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml index 53ad0929f..5040107e1 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml @@ -118,14 +118,14 @@ - + - + @@ -135,7 +135,7 @@ - + @@ -180,15 +180,21 @@ - - - + + + - + - + + memory.clk + + memory.wen memory.waddr[0:3] memory.raddr[0:3] memory.data_in[0:2] memory.data_out[0:2] + memory.ren memory.waddr[4:7] memory.raddr[4:7] memory.data_in[3:5] memory.data_out[3:5] + memory.waddr[8:11] memory.raddr[8:11] memory.data_in[6:7] memory.data_out[6:7] + @@ -682,57 +688,57 @@ - - - + + + - + - - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml index 476602970..142d286b4 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml @@ -118,14 +118,14 @@ - + - + @@ -135,7 +135,7 @@ - + @@ -176,19 +176,28 @@ clb.cout clb.O[19:10] clb.I[39:20] - + - - - + + + - + - + + memory.clk memory.waddr[0:1] memory.raddr[0:1] memory.data_in[0:0] memory.data_out[0:0] + memory.waddr[2:3] memory.raddr[2:3] memory.data_in[1:1] memory.data_out[1:1] + memory.waddr[4:5] memory.raddr[4:5] memory.data_in[2:2] memory.data_out[2:2] + memory.waddr[6:7] memory.raddr[6:7] memory.data_in[3:3] memory.data_out[3:3] + memory.waddr[8:8] memory.raddr[8:8] memory.data_in[4:4] memory.data_out[4:4] + memory.waddr[9:9] memory.raddr[9:9] memory.data_in[5:5] memory.data_out[5:5] + memory.wen memory.waddr[10:10] memory.raddr[10:10] memory.data_in[6:6] memory.data_out[6:6] + memory.ren memory.waddr[11:11] memory.raddr[11:11] memory.data_in[7:7] memory.data_out[7:7] + @@ -204,7 +213,7 @@ - + @@ -682,57 +691,57 @@ - - - + + + - + - - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + From e67095edd2282bb40d73c1a54fb680069041592c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 19:55:16 -0600 Subject: [PATCH 232/352] [HDL] Add 16k-bit dual port ram verilog --- .../verilog/dpram_2048x8.v | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v diff --git a/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v b/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v new file mode 100644 index 000000000..53561c1e4 --- /dev/null +++ b/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v @@ -0,0 +1,62 @@ +//----------------------------------------------------- +// Design Name : dpram_2048x8 +// File Name : dpram_2048x8.v +// Function : Dual port RAM 2048 x 8bit +// Coder : Xifan Tang +//----------------------------------------------------- + +module dpram_2048x8 ( + input clk, + input wen, + input ren, + input[0:11] waddr, + input[0:11] raddr, + input[0:7] data_in, + output[0:7] data_out ); + + dual_port_sram memory_0 ( + .wclk (clk), + .wen (wen), + .waddr (waddr), + .data_in (data_in), + .rclk (clk), + .ren (ren), + .raddr (raddr), + .data_out (data_out) ); + +endmodule + +//----------------------------------------------------- +// Design Name : dpram_2048x8_core +// File Name : dpram_2048x8.v +// Function : Core module of dual port RAM 2048 addresses x 8 bit +// Coder : Xifan tang +//----------------------------------------------------- +module dual_port_sram ( + input wclk, + input wen, + input[0:11] waddr, + input[0:7] data_in, + input rclk, + input ren, + input[0:11] raddr, + output[0:7] data_out ); + + reg[0:7] ram[0:2047]; + reg[0:7] internal; + + assign data_out = internal; + + always @(posedge wclk) begin + if(wen) begin + ram[waddr] <= data_in; + end + end + + always @(posedge rclk) begin + if(ren) begin + internal <= ram[raddr]; + end + end + +endmodule From 2802b0895cf1ebaadcffe8e49f8d59a11be06d01 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 19:55:46 -0600 Subject: [PATCH 233/352] [HDL] Add yosys technology library for reworked architecture using 16k-bit DPRAM --- ..._tileable_adder_chain_mem16K_40nm_bram.txt | 18 ++++++ ...ileable_adder_chain_mem16K_40nm_bram_map.v | 21 +++++++ ...ileable_adder_chain_mem16K_40nm_cell_sim.v | 58 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt create mode 100644 openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v create mode 100644 openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt new file mode 100644 index 000000000..8cbf62755 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt @@ -0,0 +1,18 @@ +bram $__MY_DPRAM_2048x8 + init 0 + abits 12 + dbits 8 + groups 2 + ports 1 1 + wrmode 1 0 + enable 1 1 + transp 0 0 + clocks 1 1 + clkpol 1 1 +endbram + +match $__MY_DPRAM_2048x8 + min efficiency 0 + make_transp +endmatch + diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v new file mode 100644 index 000000000..cc4881d77 --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v @@ -0,0 +1,21 @@ +module $__MY_DPRAM_2048x8 ( + output [0:7] B1DATA, + input CLK1, + input [0:11] B1ADDR, + input [0:11] A1ADDR, + input [0:7] A1DATA, + input A1EN, + input B1EN ); + + generate + dpram_2048x8 #() _TECHMAP_REPLACE_ ( + .clk (CLK1), + .wen (A1EN), + .waddr (A1ADDR), + .data_in (A1DATA), + .ren (B1EN), + .raddr (B1ADDR), + .data_out (B1DATA) ); + endgenerate + +endmodule diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v new file mode 100644 index 000000000..5e772bf8d --- /dev/null +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v @@ -0,0 +1,58 @@ +//----------------------------- +// Dual-port RAM 2048x8 bit (8Kbit) +// Core logic +//----------------------------- +module dpram_2048x8_core ( + input wclk, + input wen, + input [0:11] waddr, + input [0:7] data_in, + input rclk, + input ren, + input [0:11] raddr, + output [0:7] data_out ); + + reg [0:7] ram[0:2047]; + reg [0:7] internal; + + assign data_out = internal; + + always @(posedge wclk) begin + if(wen) begin + ram[waddr] <= data_in; + end + end + + always @(posedge rclk) begin + if(ren) begin + internal <= ram[raddr]; + end + end + +endmodule + +//----------------------------- +// Dual-port RAM 2048x8 bit (8Kbit) wrapper +// where the read clock and write clock +// are combined to a unified clock +//----------------------------- +module dpram_2048x8 ( + input clk, + input wen, + input ren, + input [0:11] waddr, + input [0:11] raddr, + input [0:7] data_in, + output [0:7] data_out ); + + dpram_2048x8_core memory_0 ( + .wclk (clk), + .wen (wen), + .waddr (waddr), + .data_in (data_in), + .rclk (clk), + .ren (ren), + .raddr (raddr), + .data_out (data_out) ); + +endmodule From fdfbdc46137afe8a5526104912ac173af0347560 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 20:05:04 -0600 Subject: [PATCH 234/352] [Test] Update task configuration files to use dedicated yosys script --- .../bram/dpram16k/config/task.conf | 20 +++++++++------- .../bram/wide_dpram16k/config/task.conf | 24 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf index b7d8715ec..3aa8178f1 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf @@ -9,29 +9,33 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 20*60 -fpga_flow=vpr_blif +fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +# VPR parameter openfpga_vpr_device_layout=3x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/*.v [SYNTHESIS_PARAM] -bench0_top = and2 -bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act -bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v -bench0_chan_width = 300 +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys +bench0_top = fifo [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= diff --git a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf index d8dc5d26d..96175116c 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf @@ -9,29 +9,33 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 20*60 -fpga_flow=vpr_blif +fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=4x4 +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +# VPR parameter +openfpga_vpr_device_layout=4x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/*.v [SYNTHESIS_PARAM] -bench0_top = and2 -bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act -bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v -bench0_chan_width = 300 +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys +bench0_top = fifo [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From dd467808651c2bb09b2704b80fb527a3351f7be5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 21:44:27 -0600 Subject: [PATCH 235/352] [Script] Update yosys script using BRAMs --- openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys index d680cf71c..6a8bf372b 100644 --- a/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys +++ b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys @@ -27,9 +27,6 @@ opt_clean deminout opt -######################### -# Run coarse synthesis -######################### opt_expr opt_clean check @@ -38,8 +35,13 @@ wreduce -keepdc peepopt pmuxtree opt_clean + +######################### +# Run coarse synthesis +######################### # Extract arithmetic functions alumacc +share opt fsm # Run a quick follow-up optimization to sweep out unused nets/signals From 5a85ec9fa0ee4f0e3fbc6714ac40aadf1f309467 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 22:09:10 -0600 Subject: [PATCH 236/352] [Benchmark] Reduce default size of FIFO to limit the number of LUTs and BRAMs to be synthesised --- openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v | 6 +++--- .../micro_benchmark/fifo/rtl/sync_dual_port_ram.v | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v index af1bc6921..65dc95d11 100644 --- a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v +++ b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/fifo.v @@ -2,8 +2,8 @@ // Reference: // https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/ module fifo - #( parameter ADDRESS_WIDTH = 12, // number of words in ram - DATA_WIDTH = 8 // number of bits in word + #( parameter ADDRESS_WIDTH = 4, // number of words in ram + DATA_WIDTH = 4 // number of bits in word ) // IO ports @@ -94,4 +94,4 @@ module fifo // assign full/empty status to output ports assign full = full_reg; assign empty = empty_reg; -endmodule \ No newline at end of file +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v index 5914129e4..bd1de2b4b 100644 --- a/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v +++ b/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/sync_dual_port_ram.v @@ -2,8 +2,8 @@ // Reference: // https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/ module sync_dual_port_ram - #( parameter ADDRESS_WIDTH = 12, // number of words in ram - DATA_WIDTH = 8 // number of bits in word + #( parameter ADDRESS_WIDTH = 4, // number of words in ram + DATA_WIDTH = 4 // number of bits in word ) // IO ports @@ -32,4 +32,4 @@ module sync_dual_port_ram // assignments for two data out ports assign read_data_out = ram[read_address_reg]; assign write_data_out = ram[write_address_reg]; -endmodule \ No newline at end of file +endmodule From 7e2368158e3364aea2e49c747fa1b80003efe038 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 22:12:30 -0600 Subject: [PATCH 237/352] [Benchmark] move benchmarks to microbenchmark category --- .../pipelined_8bit_adder/pipelined_8bit_adder.act | 0 .../pipelined_8bit_adder/pipelined_8bit_adder.blif | 0 .../pipelined_8bit_adder/pipelined_8bit_adder.v | 0 .../pipelined_8bit_adder_formal_random_top_tb.v | 0 .../{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.act | 0 .../{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.blif | 0 .../{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.v | 0 .../{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.act | 0 .../{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.blif | 0 .../{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.v | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename openfpga_flow/benchmarks/{ => micro_benchmark}/pipelined_8bit_adder/pipelined_8bit_adder.act (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/pipelined_8bit_adder/pipelined_8bit_adder.blif (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/pipelined_8bit_adder/pipelined_8bit_adder.v (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.act (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.blif (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k4_N4/K4N4_test_modes.v (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.act (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.blif (100%) rename openfpga_flow/benchmarks/{ => micro_benchmark}/test_modes/k6_N10/K6N10_test_modes.v (100%) diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act b/openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.act similarity index 100% rename from openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act rename to openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.act diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif b/openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.blif similarity index 100% rename from openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif rename to openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.blif diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v b/openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.v similarity index 100% rename from openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v rename to openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder.v diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v b/openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v similarity index 100% rename from openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v rename to openfpga_flow/benchmarks/micro_benchmark/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v diff --git a/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.act b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.act similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.act rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.act diff --git a/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.blif b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.blif similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.blif rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.blif diff --git a/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.v b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.v similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.v rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k4_N4/K4N4_test_modes.v diff --git a/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.act b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.act similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.act rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.act diff --git a/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.blif b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.blif similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.blif rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.blif diff --git a/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.v b/openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.v similarity index 100% rename from openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.v rename to openfpga_flow/benchmarks/micro_benchmark/test_modes/k6_N10/K6N10_test_modes.v From 3c1c33bf1e1e1674eabf956e181d8a737b4b9e9f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 22:51:43 -0600 Subject: [PATCH 238/352] [Benchmark] Add a microbenchmark just fit 16k dual port ram --- .../dual_port_ram_16k/dual_port_ram_16k.v | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v new file mode 100644 index 000000000..a27801d9e --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v @@ -0,0 +1,58 @@ +//----------------------------------------------------- +// Design Name : dual_port_ram_16k +// File Name : dpram.v +// Function : Dual port RAM 2048x8bit +// Coder : Aurelien +//----------------------------------------------------- + +module dual_port_ram_16k ( + input clk, + input wen, + input ren, + input [11:0] waddr, + input [11:0] raddr, + input [7:0] din, + output [7:0] dout +); + + dual_port_sram_16kb memory_0 ( + .wclk (clk), + .wen (wen), + .waddr (waddr), + .data_in (din), + .rclk (clk), + .ren (ren), + .raddr (raddr), + .data_out (dout) ); + +endmodule + +module dual_port_sram_16kb ( + input wclk, + input wen, + input [11:0] waddr, + input [7:0] data_in, + input rclk, + input ren, + input [11:0] raddr, + output [7:0] data_out +); + + reg [7:0] ram[2047:0]; + reg [7:0] internal; + + assign data_out = internal; + + always @(posedge wclk) begin + if(wen) begin + ram[waddr] <= data_in; + end + end + + always @(posedge rclk) begin + if(ren) begin + internal <= ram[raddr]; + end + end + +endmodule From 7d059f74073cfe17866377bd24ad6bf78566e478 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 23:33:20 -0600 Subject: [PATCH 239/352] [Benchmark] Bug fix in dual port ram 16k benchmark --- .../dual_port_ram_16k/dual_port_ram_16k.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v index a27801d9e..60f165ab0 100644 --- a/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v +++ b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v @@ -1,16 +1,16 @@ //----------------------------------------------------- // Design Name : dual_port_ram_16k -// File Name : dpram.v +// File Name : dual_port_ram_16k.v // Function : Dual port RAM 2048x8bit -// Coder : Aurelien +// Coder : Xifan Tang //----------------------------------------------------- module dual_port_ram_16k ( input clk, input wen, input ren, - input [11:0] waddr, - input [11:0] raddr, + input [10:0] waddr, + input [10:0] raddr, input [7:0] din, output [7:0] dout ); @@ -30,11 +30,11 @@ endmodule module dual_port_sram_16kb ( input wclk, input wen, - input [11:0] waddr, + input [10:0] waddr, input [7:0] data_in, input rclk, input ren, - input [11:0] raddr, + input [10:0] raddr, output [7:0] data_out ); From 0bec4b3f321de75286376a04fa86071805f7d00f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 23:34:42 -0600 Subject: [PATCH 240/352] [Test] Update task configuration to use proper openfpgashell script --- .../tasks/fpga_verilog/bram/dpram16k/config/task.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf index 3aa8178f1..c340d7f9f 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf @@ -16,7 +16,7 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml # Yosys script parameters @@ -30,12 +30,12 @@ openfpga_vpr_device_layout=3x2 arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/*.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys -bench0_top = fifo +bench0_top = dual_port_ram_16k [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 834657f2da5b9584a71d2aedcc007d95f860add6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 23:41:14 -0600 Subject: [PATCH 241/352] [Arch] Patch arch using 16kbit DPRAM due to wrong addr sizes --- ...c_N10_adder_chain_mem16K_40nm_openfpga.xml | 6 +++--- ...c_N10_tileable_adder_chain_mem16K_40nm.xml | 19 +++++++++++-------- ..._tileable_adder_chain_wide_mem16K_40nm.xml | 19 +++++++++++-------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml index 19064e7b6..124fed331 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml @@ -147,7 +147,7 @@ - + @@ -198,8 +198,8 @@ - - + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml index 5040107e1..93423a81d 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml @@ -164,6 +164,7 @@ + @@ -180,20 +181,22 @@ - - + + - + + + memory.clk memory.wen memory.waddr[0:3] memory.raddr[0:3] memory.data_in[0:2] memory.data_out[0:2] memory.ren memory.waddr[4:7] memory.raddr[4:7] memory.data_in[3:5] memory.data_out[3:5] - memory.waddr[8:11] memory.raddr[8:11] memory.data_in[6:7] memory.data_out[6:7] + memory.waddr[8:10] memory.raddr[8:10] memory.data_in[6:7] memory.data_out[6:7] @@ -688,8 +691,8 @@ - - + + @@ -701,8 +704,8 @@ --> - - + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml index 142d286b4..c6f578260 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml @@ -164,6 +164,7 @@ + @@ -180,14 +181,16 @@ - - + + - + + + memory.clk memory.waddr[0:1] memory.raddr[0:1] memory.data_in[0:0] memory.data_out[0:0] memory.waddr[2:3] memory.raddr[2:3] memory.data_in[1:1] memory.data_out[1:1] @@ -196,7 +199,7 @@ memory.waddr[8:8] memory.raddr[8:8] memory.data_in[4:4] memory.data_out[4:4] memory.waddr[9:9] memory.raddr[9:9] memory.data_in[5:5] memory.data_out[5:5] memory.wen memory.waddr[10:10] memory.raddr[10:10] memory.data_in[6:6] memory.data_out[6:6] - memory.ren memory.waddr[11:11] memory.raddr[11:11] memory.data_in[7:7] memory.data_out[7:7] + memory.ren memory.data_in[7:7] memory.data_out[7:7] @@ -691,8 +694,8 @@ - - + + @@ -704,8 +707,8 @@ --> - - + + From 411af109337f6f9cbfda86b790e6843cfb12666b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 23:41:47 -0600 Subject: [PATCH 242/352] [Script] Patch yosys script for 16kbit dual port RAM --- .../k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt | 2 +- ...6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v | 4 ++-- ...6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt index 8cbf62755..327dbe9bf 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt @@ -1,6 +1,6 @@ bram $__MY_DPRAM_2048x8 init 0 - abits 12 + abits 11 dbits 8 groups 2 ports 1 1 diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v index cc4881d77..35ec892dc 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v @@ -1,8 +1,8 @@ module $__MY_DPRAM_2048x8 ( output [0:7] B1DATA, input CLK1, - input [0:11] B1ADDR, - input [0:11] A1ADDR, + input [0:10] B1ADDR, + input [0:10] A1ADDR, input [0:7] A1DATA, input A1EN, input B1EN ); diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v index 5e772bf8d..9fc6a1aa1 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v @@ -5,11 +5,11 @@ module dpram_2048x8_core ( input wclk, input wen, - input [0:11] waddr, + input [0:10] waddr, input [0:7] data_in, input rclk, input ren, - input [0:11] raddr, + input [0:10] raddr, output [0:7] data_out ); reg [0:7] ram[0:2047]; @@ -40,8 +40,8 @@ module dpram_2048x8 ( input clk, input wen, input ren, - input [0:11] waddr, - input [0:11] raddr, + input [0:10] waddr, + input [0:10] raddr, input [0:7] data_in, output [0:7] data_out ); From 63309ba72ba6c8f7e94fa2b0e0b1b9cc36fc8a20 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 27 Apr 2021 23:42:31 -0600 Subject: [PATCH 243/352] [HDL] Patch dpram cell --- .../openfpga_cell_library/verilog/dpram_2048x8.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v b/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v index 53561c1e4..fa56d30cb 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dpram_2048x8.v @@ -9,8 +9,8 @@ module dpram_2048x8 ( input clk, input wen, input ren, - input[0:11] waddr, - input[0:11] raddr, + input[0:10] waddr, + input[0:10] raddr, input[0:7] data_in, output[0:7] data_out ); @@ -35,11 +35,11 @@ endmodule module dual_port_sram ( input wclk, input wen, - input[0:11] waddr, + input[0:10] waddr, input[0:7] data_in, input rclk, input ren, - input[0:11] raddr, + input[0:10] raddr, output[0:7] data_out ); reg[0:7] ram[0:2047]; From 79b27a6329a8ed8ae395e38b9ed1d35411ed52d5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 10:29:09 -0600 Subject: [PATCH 244/352] [Arch] Patch arch using DPRAM block with wide = 2 --- .../k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml index c6f578260..da1d573d5 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml @@ -195,7 +195,7 @@ memory.clk memory.waddr[0:1] memory.raddr[0:1] memory.data_in[0:0] memory.data_out[0:0] memory.waddr[2:3] memory.raddr[2:3] memory.data_in[1:1] memory.data_out[1:1] memory.waddr[4:5] memory.raddr[4:5] memory.data_in[2:2] memory.data_out[2:2] - memory.waddr[6:7] memory.raddr[6:7] memory.data_in[3:3] memory.data_out[3:3] + memory.waddr[6:7] memory.raddr[6:7] memory.data_in[3:3] memory.data_out[3:3] memory.waddr[8:8] memory.raddr[8:8] memory.data_in[4:4] memory.data_out[4:4] memory.waddr[9:9] memory.raddr[9:9] memory.data_in[5:5] memory.data_out[5:5] memory.wen memory.waddr[10:10] memory.raddr[10:10] memory.data_in[6:6] memory.data_out[6:6] From 5c729657efdfd201c608e0be708e83cd65e2ec30 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 10:31:22 -0600 Subject: [PATCH 245/352] [Test] Bug fix in test case for DPRAM whose width = 2 --- .../tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf index 96175116c..441d6ff82 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf @@ -30,12 +30,12 @@ openfpga_vpr_device_layout=4x2 arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/fifo/rtl/*.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys -bench0_top = fifo +bench0_top = dual_port_ram_16k [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From be98775ae534810b812ec4ea0d729484b4e23d82 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 10:45:10 -0600 Subject: [PATCH 246/352] [Arch] Reduce the size of DPRAM in example architecture to accelerate testing --- ...c_N10_adder_chain_mem16K_40nm_openfpga.xml | 279 ------------------ ...c_N10_tileable_adder_chain_mem1K_40nm.xml} | 64 ++-- ..._tileable_adder_chain_wide_mem1K_40nm.xml} | 72 ++--- 3 files changed, 68 insertions(+), 347 deletions(-) delete mode 100644 openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml rename openfpga_flow/vpr_arch/{k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml => k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml} (95%) rename openfpga_flow/vpr_arch/{k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml => k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml} (94%) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml deleted file mode 100644 index 124fed331..000000000 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10e-12 - - - 10e-12 - - - - - - - - - 10e-12 - - - 10e-12 - - - - - - - - - 10e-12 - - - 10e-12 - - - - - - - - - - - - 10e-12 5e-12 - - - 10e-12 5e-12 - - - - - - - - - - - - - 10e-12 5e-12 5e-12 - - - 10e-12 5e-12 5e-12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml similarity index 95% rename from openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml rename to openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml index 93423a81d..170e65818 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml @@ -118,7 +118,7 @@ - + @@ -181,8 +181,8 @@ - - + + @@ -194,9 +194,9 @@ memory.clk - memory.wen memory.waddr[0:3] memory.raddr[0:3] memory.data_in[0:2] memory.data_out[0:2] - memory.ren memory.waddr[4:7] memory.raddr[4:7] memory.data_in[3:5] memory.data_out[3:5] - memory.waddr[8:10] memory.raddr[8:10] memory.data_in[6:7] memory.data_out[6:7] + memory.wen memory.waddr[0:2] memory.raddr[0:2] memory.data_in[0:2] memory.data_out[0:2] + memory.ren memory.waddr[3:5] memory.raddr[3:5] memory.data_in[3:5] memory.data_out[3:5] + memory.waddr[6:6] memory.raddr[6:6] memory.data_in[6:7] memory.data_out[6:7] @@ -691,57 +691,57 @@ - - + + - - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml similarity index 94% rename from openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml rename to openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml index da1d573d5..0b7820139 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml @@ -118,7 +118,7 @@ - + @@ -181,8 +181,8 @@ - - + + @@ -192,13 +192,13 @@ - memory.clk memory.waddr[0:1] memory.raddr[0:1] memory.data_in[0:0] memory.data_out[0:0] - memory.waddr[2:3] memory.raddr[2:3] memory.data_in[1:1] memory.data_out[1:1] - memory.waddr[4:5] memory.raddr[4:5] memory.data_in[2:2] memory.data_out[2:2] - memory.waddr[6:7] memory.raddr[6:7] memory.data_in[3:3] memory.data_out[3:3] - memory.waddr[8:8] memory.raddr[8:8] memory.data_in[4:4] memory.data_out[4:4] - memory.waddr[9:9] memory.raddr[9:9] memory.data_in[5:5] memory.data_out[5:5] - memory.wen memory.waddr[10:10] memory.raddr[10:10] memory.data_in[6:6] memory.data_out[6:6] + memory.clk memory.waddr[0:0] memory.raddr[0:0] memory.data_in[0:0] memory.data_out[0:0] + memory.waddr[1:1] memory.raddr[1:1] memory.data_in[1:1] memory.data_out[1:1] + memory.waddr[2:2] memory.raddr[2:2] memory.data_in[2:2] memory.data_out[2:2] + memory.waddr[3:3] memory.raddr[3:3] memory.data_in[3:3] memory.data_out[3:3] + memory.waddr[4:4] memory.raddr[4:4] memory.data_in[4:4] memory.data_out[4:4] + memory.waddr[5:5] memory.raddr[5:5] memory.data_in[5:5] memory.data_out[5:5] + memory.wen memory.waddr[5:5] memory.raddr[5:5] memory.data_in[6:6] memory.data_out[6:6] memory.ren memory.data_in[7:7] memory.data_out[7:7] @@ -694,57 +694,57 @@ - - + + - - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + From ec4b60f3cc7daca3020a337f45d5db14c2428734 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 10:47:17 -0600 Subject: [PATCH 247/352] [Arch] Add example arch using 1-kbit DPRAM --- ...ac_N10_adder_chain_mem1K_40nm_openfpga.xml | 279 ++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml new file mode 100644 index 000000000..6af9952f1 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c24edbd6740df55f551d85c0fdba113f5834aecb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 10:55:59 -0600 Subject: [PATCH 248/352] [Script] Update yosys script due to arch changes in DPRAM sizes --- ..._tileable_adder_chain_mem1K_40nm_bram.txt} | 6 +++--- ...ileable_adder_chain_mem1K_40nm_bram_map.v} | 8 ++++---- ...ileable_adder_chain_mem1K_40nm_cell_sim.v} | 20 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) rename openfpga_flow/openfpga_yosys_techlib/{k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt => k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt} (73%) rename openfpga_flow/openfpga_yosys_techlib/{k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v => k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v} (72%) rename openfpga_flow/openfpga_yosys_techlib/{k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v => k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v} (76%) diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt similarity index 73% rename from openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt rename to openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt index 327dbe9bf..51617f271 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt @@ -1,6 +1,6 @@ -bram $__MY_DPRAM_2048x8 +bram $__MY_DPRAM_128x8 init 0 - abits 11 + abits 7 dbits 8 groups 2 ports 1 1 @@ -11,7 +11,7 @@ bram $__MY_DPRAM_2048x8 clkpol 1 1 endbram -match $__MY_DPRAM_2048x8 +match $__MY_DPRAM_128x8 min efficiency 0 make_transp endmatch diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v similarity index 72% rename from openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v rename to openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v index 35ec892dc..8cf462c1a 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v @@ -1,14 +1,14 @@ -module $__MY_DPRAM_2048x8 ( +module $__MY_DPRAM_128x8 ( output [0:7] B1DATA, input CLK1, - input [0:10] B1ADDR, - input [0:10] A1ADDR, + input [0:6] B1ADDR, + input [0:6] A1ADDR, input [0:7] A1DATA, input A1EN, input B1EN ); generate - dpram_2048x8 #() _TECHMAP_REPLACE_ ( + dpram_128x8 #() _TECHMAP_REPLACE_ ( .clk (CLK1), .wen (A1EN), .waddr (A1ADDR), diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v similarity index 76% rename from openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v rename to openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v index 9fc6a1aa1..9ec66e6ee 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v @@ -1,18 +1,18 @@ //----------------------------- -// Dual-port RAM 2048x8 bit (8Kbit) +// Dual-port RAM 128x8 bit (1Kbit) // Core logic //----------------------------- -module dpram_2048x8_core ( +module dpram_128x8_core ( input wclk, input wen, - input [0:10] waddr, + input [0:6] waddr, input [0:7] data_in, input rclk, input ren, - input [0:10] raddr, + input [0:6] raddr, output [0:7] data_out ); - reg [0:7] ram[0:2047]; + reg [0:7] ram[0:127]; reg [0:7] internal; assign data_out = internal; @@ -32,20 +32,20 @@ module dpram_2048x8_core ( endmodule //----------------------------- -// Dual-port RAM 2048x8 bit (8Kbit) wrapper +// Dual-port RAM 128x8 bit (1Kbit) wrapper // where the read clock and write clock // are combined to a unified clock //----------------------------- -module dpram_2048x8 ( +module dpram_128x8 ( input clk, input wen, input ren, - input [0:10] waddr, - input [0:10] raddr, + input [0:6] waddr, + input [0:6] raddr, input [0:7] data_in, output [0:7] data_out ); - dpram_2048x8_core memory_0 ( + dpram_128x8_core memory_0 ( .wclk (clk), .wen (wen), .waddr (waddr), From a571b063b666842332647a2ffafd6b0960148f31 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 11:26:31 -0600 Subject: [PATCH 249/352] [Benchmark] Add 1k DPRAM benchmark which can fit new arch --- .../dual_port_ram_1k/dual_port_ram_1k.v | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v new file mode 100644 index 000000000..c8bcc4e58 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v @@ -0,0 +1,58 @@ +//----------------------------------------------------- +// Design Name : dual_port_ram_1k +// File Name : dual_port_ram_1k.v +// Function : Dual port RAM 128x8bit +// Coder : Xifan Tang +//----------------------------------------------------- + +module dual_port_ram_1k ( + input clk, + input wen, + input ren, + input [6:0] waddr, + input [6:0] raddr, + input [7:0] din, + output [7:0] dout +); + + dual_port_sram_1kb memory_0 ( + .wclk (clk), + .wen (wen), + .waddr (waddr), + .data_in (din), + .rclk (clk), + .ren (ren), + .raddr (raddr), + .data_out (dout) ); + +endmodule + +module dual_port_sram_1kb ( + input wclk, + input wen, + input [6:0] waddr, + input [7:0] data_in, + input rclk, + input ren, + input [6:0] raddr, + output [7:0] data_out +); + + reg [7:0] ram[127:0]; + reg [7:0] internal; + + assign data_out = internal; + + always @(posedge wclk) begin + if(wen) begin + ram[waddr] <= data_in; + end + end + + always @(posedge rclk) begin + if(ren) begin + internal <= ram[raddr]; + end + end + +endmodule From 117cea295d75181a7706789159b8fe71cd878ed9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 11:28:23 -0600 Subject: [PATCH 250/352] [Arch] Patch architecture to be compatible with pin names of DPRAM cell --- .../k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml index 6af9952f1..e66611fb0 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml @@ -200,10 +200,10 @@ - + - + From b72d4bd8076037599e8cada9a39995838786ccc5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 11:28:53 -0600 Subject: [PATCH 251/352] [Test] Update test case for 1kbit DPRAM architectures --- .../bram/{dpram16k => dpram1k}/config/task.conf | 14 +++++++------- .../config/task.conf | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) rename openfpga_flow/tasks/fpga_verilog/bram/{dpram16k => dpram1k}/config/task.conf (82%) rename openfpga_flow/tasks/fpga_verilog/bram/{wide_dpram16k => wide_dpram1k}/config/task.conf (82%) diff --git a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/dpram1k/config/task.conf similarity index 82% rename from openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf rename to openfpga_flow/tasks/fpga_verilog/bram/dpram1k/config/task.conf index c340d7f9f..67ab566f4 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/dpram1k/config/task.conf @@ -17,25 +17,25 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml # Yosys script parameters -yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v -yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt -yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v # VPR parameter openfpga_vpr_device_layout=3x2 [ARCHITECTURES] -arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys -bench0_top = dual_port_ram_16k +bench0_top = dual_port_ram_1k [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= diff --git a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram1k/config/task.conf similarity index 82% rename from openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf rename to openfpga_flow/tasks/fpga_verilog/bram/wide_dpram1k/config/task.conf index 441d6ff82..234150aa1 100644 --- a/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram16k/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/bram/wide_dpram1k/config/task.conf @@ -17,25 +17,25 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml # Yosys script parameters -yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_cell_sim.v -yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram.txt -yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem16K_40nm_bram_map.v +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v # VPR parameter openfpga_vpr_device_layout=4x2 [ARCHITECTURES] -arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_16k/dual_port_ram_16k.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v [SYNTHESIS_PARAM] bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys -bench0_top = dual_port_ram_16k +bench0_top = dual_port_ram_1k [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 870432e7f1084f0c4553d0729c1992c0441e68d0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 12:45:52 -0600 Subject: [PATCH 252/352] [Test] Patch regression test script due to the change of DPRAM test case --- .../regression_test_scripts/fpga_verilog_reg_test.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 8f64816de..70137dd77 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -38,11 +38,11 @@ run-task fpga_verilog/adder/hard_adder --debug --show_thread_logs echo -e "Testing Verilog generation with soft adder chain in CLBs "; run-task fpga_verilog/adder/soft_adder --debug --show_thread_logs -echo -e "Testing Verilog generation with 16k block RAMs "; -run-task fpga_verilog/bram/dpram16k --debug --show_thread_logs +echo -e "Testing Verilog generation with 1k block RAMs "; +run-task fpga_verilog/bram/dpram1k --debug --show_thread_logs -echo -e "Testing Verilog generation with 16k block RAMs spanning two columns "; -run-task fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs +echo -e "Testing Verilog generation with 1k block RAMs spanning two columns "; +run-task fpga_verilog/bram/wide_dpram1k --debug --show_thread_logs echo -e "Testing Verilog generation with heterogeneous fabric using 8-bit single-mode multipliers "; run-task fpga_verilog/dsp/single_mode_mult_8x8 --debug --show_thread_logs From bc34efe3378e6c8961a35b55bd5dcb24fd582f26 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 14:32:17 -0600 Subject: [PATCH 253/352] [Arch] Bug fix in the architecture using BRAM spanning two columns --- .../k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml index 0b7820139..e4119f1cb 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml @@ -198,7 +198,7 @@ memory.waddr[3:3] memory.raddr[3:3] memory.data_in[3:3] memory.data_out[3:3] memory.waddr[4:4] memory.raddr[4:4] memory.data_in[4:4] memory.data_out[4:4] memory.waddr[5:5] memory.raddr[5:5] memory.data_in[5:5] memory.data_out[5:5] - memory.wen memory.waddr[5:5] memory.raddr[5:5] memory.data_in[6:6] memory.data_out[6:6] + memory.wen memory.waddr[6:6] memory.raddr[6:6] memory.data_in[6:6] memory.data_out[6:6] memory.ren memory.data_in[7:7] memory.data_out[7:7] From f77b81fe5bbb1b17ef7185cf3379b410a55464c8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 28 Apr 2021 15:05:30 -0600 Subject: [PATCH 254/352] [Arch] recover the mem16k arch as it is used in other test cases --- ...c_N10_adder_chain_mem16K_40nm_openfpga.xml | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml new file mode 100644 index 000000000..5259e5e03 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 16fff90607b77685272fd61e65831cc1eb2d0399 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 6 May 2021 15:17:27 -0600 Subject: [PATCH 255/352] [Benchmark] Add microbenchmark 1-bit blinking --- .../micro_benchmark/blinking/blinking.v | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/blinking/blinking.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/blinking/blinking.v b/openfpga_flow/benchmarks/micro_benchmark/blinking/blinking.v new file mode 100644 index 000000000..b8587055c --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/blinking/blinking.v @@ -0,0 +1,17 @@ +// ------------------------------ +// Design Name: Blinking +// Functionality: 1-bit blinking +// ------------------------------ +module blinking( + clk, + out +); + +input clk; +output out; + + always @(posedge clk) begin + out = ~out; + end + +endmodule From f1658cb735c27df5bef0eac617f37743618b695d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 6 May 2021 15:17:45 -0600 Subject: [PATCH 256/352] [Test] Deploy blinking to test cases --- .../full_testbench/fast_configuration_chain/config/task.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf index 6f4200ffe..1967bd2a4 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf @@ -27,6 +27,7 @@ arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/blinking/blinking.v [SYNTHESIS_PARAM] bench0_top = and2 @@ -38,5 +39,8 @@ bench1_chan_width = 300 bench2_top = and2_latch bench2_chan_width = 300 +bench3_top = blinking +bench3_chan_width = 300 + [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 01b3a96e4bd3223415826cd80545debae28f347f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 11:22:01 -0600 Subject: [PATCH 257/352] [Tool] Add report bitstream distribution functionality to architecture bitstream library --- .../src/bitstream_manager_utils.cpp | 22 ++++ .../src/bitstream_manager_utils.h | 3 + .../report_arch_bitstream_distribution.cpp | 121 ++++++++++++++++++ .../src/report_arch_bitstream_distribution.h | 23 ++++ .../test/test_arch_bitstream.cpp | 16 ++- 5 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp create mode 100644 libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.cpp index 8968b8d1c..721c147d4 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.cpp @@ -71,5 +71,27 @@ size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamMa return curr_index; } +/******************************************************************** + * Find the total number of configuration bits under a block + * As configuration bits are stored only under the leaf blocks, + * this function will recursively visit all the child blocks + * until reaching a leaf block, where we collect the number of bits + *******************************************************************/ +size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager, + const ConfigBlockId& block) { + /* For leaf block, return directly with the number of bits, because it has not child block */ + if (0 < bitstream_manager.block_bits(block).size()) { + VTR_ASSERT_SAFE(bitstream_manager.block_children(block).empty()); + return bitstream_manager.block_bits(block).size(); + } + + size_t sum_of_bits = 0; + /* Dive to child blocks if this block has any */ + for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) { + sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, child_block); + } + + return sum_of_bits; +} } /* end namespace openfpga */ diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.h b/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.h index 328394b01..e1e8b8567 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager_utils.h @@ -22,6 +22,9 @@ std::vector find_bitstream_manager_top_blocks(const BitstreamMana size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager, const ConfigBitId& bit_id); +size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager, + const ConfigBlockId& block); + } /* end namespace openfpga */ #endif diff --git a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp new file mode 100644 index 000000000..e5a1d47d9 --- /dev/null +++ b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp @@ -0,0 +1,121 @@ +/******************************************************************** + * This file includes functions that report distribution of bitstream by blocks + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_digest.h" +#include "openfpga_tokenizer.h" +#include "openfpga_version.h" + +#include "openfpga_reserved_words.h" + +#include "bitstream_manager_utils.h" +#include "report_arch_bitstream_distribution.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function write header information for an XML file of bitstream distribution + *******************************************************************/ +static +void report_architecture_bitstream_distribution_xml_file_head(std::fstream& fp) { + valid_file_stream(fp); + + auto end = std::chrono::system_clock::now(); + std::time_t end_time = std::chrono::system_clock::to_time_t(end); + + fp << " " << std::endl; + fp << std::endl; +} + +/******************************************************************** + * Recursively report the bitstream distribution of a block to a file + * This function will use a Depth-First Search in outputting bitstream + * for each block + * For block with child blocks, we visit each child recursively + * The reporting can be stopped at a given maximum hierarchy level + * which is used to limit the length of the report + *******************************************************************/ +static +void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp, + const BitstreamManager& bitstream_manager, + const ConfigBlockId& block, + const size_t& max_hierarchy_level, + const size_t& hierarchy_level) { + valid_file_stream(fp); + + if (hierarchy_level > max_hierarchy_level) { + return; + } + + /* Write the bitstream distribution of this block */ + write_tab_to_file(fp, hierarchy_level); + fp << "" << std::endl; + + /* Dive to child blocks if this block has any */ + for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) { + rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, child_block, + max_hierarchy_level, hierarchy_level + 1); + } + + write_tab_to_file(fp, hierarchy_level); + fp << "" < top_block = find_bitstream_manager_top_blocks(bitstream_manager); + /* Make sure we have only 1 top block */ + VTR_ASSERT(1 == top_block.size()); + + /* Write bitstream, block by block, in a recursive way */ + rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level, 0); + + /* Close file handler */ + fp.close(); +} + +} /* end namespace openfpga */ diff --git a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h new file mode 100644 index 000000000..aedbce765 --- /dev/null +++ b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h @@ -0,0 +1,23 @@ +#ifndef REPORT_ARCH_BITSTREAM_DISTRIBUTION_H +#define REPORT_ARCH_BITSTREAM_DISTRIBUTION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "bitstream_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager, + const std::string& fname, + const size_t& max_hierarchy_level = 1); + +} /* end namespace openfpga */ + +#endif diff --git a/libopenfpga/libfpgabitstream/test/test_arch_bitstream.cpp b/libopenfpga/libfpgabitstream/test/test_arch_bitstream.cpp index 88d00601e..d71b077c4 100644 --- a/libopenfpga/libfpgabitstream/test/test_arch_bitstream.cpp +++ b/libopenfpga/libfpgabitstream/test/test_arch_bitstream.cpp @@ -10,17 +10,18 @@ /* Headers from fabric key */ #include "read_xml_arch_bitstream.h" #include "write_xml_arch_bitstream.h" +#include "report_arch_bitstream_distribution.h" int main(int argc, const char** argv) { - /* Ensure we have only one or two argument */ - VTR_ASSERT((2 == argc) || (3 == argc)); + /* Ensure we have only one or two or 3 argument */ + VTR_ASSERT((2 == argc) || (3 == argc) || (4 == argc)); /* Parse the bitstream from an XML file */ openfpga::BitstreamManager test_bitstream = openfpga::read_xml_architecture_bitstream(argv[1]); VTR_LOG("Read the bitstream from an XML file: %s.\n", argv[1]); - /* Output the circuit library to an XML file + /* Output the bitstream database to an XML file * This is optional only used when there is a second argument */ if (3 <= argc) { @@ -28,6 +29,15 @@ int main(int argc, const char** argv) { VTR_LOG("Echo the bitstream to an XML file: %s.\n", argv[2]); } + /* Output the bitstream distribution to an XML file + * This is optional only used when there is a third argument + */ + if (4 <= argc) { + openfpga::report_architecture_bitstream_distribution(test_bitstream, argv[3]); + VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n", + argv[3]); + } + } From db9bb9124e9462cda4780e9306cf3815fc837eba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 11:41:25 -0600 Subject: [PATCH 258/352] [Tool] Add report bitstream distribution command to openfpga shell --- .../report_arch_bitstream_distribution.cpp | 9 ++-- .../src/report_arch_bitstream_distribution.h | 6 +-- openfpga/src/base/openfpga_bitstream.cpp | 38 +++++++++++++++++ openfpga/src/base/openfpga_bitstream.h | 3 ++ .../src/base/openfpga_bitstream_command.cpp | 42 +++++++++++++++++++ 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp index e5a1d47d9..1667b3e86 100644 --- a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp +++ b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.cpp @@ -86,12 +86,13 @@ void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp, * Notes: * - The output format is a table whose format is compatible with RST files *******************************************************************/ -void report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager, - const std::string& fname, - const size_t& max_hierarchy_level) { +int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager, + const std::string& fname, + const size_t& max_hierarchy_level) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { VTR_LOG_ERROR("Received empty file name to report bitstream!\n\tPlease specify a valid file name.\n"); + return 1; } std::string timer_message = std::string("Report architecture bitstream distribution into XML file '") + fname + std::string("'"); @@ -116,6 +117,8 @@ void report_architecture_bitstream_distribution(const BitstreamManager& bitstrea /* Close file handler */ fp.close(); + + return 0; } } /* end namespace openfpga */ diff --git a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h index aedbce765..322a65901 100644 --- a/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h +++ b/libopenfpga/libfpgabitstream/src/report_arch_bitstream_distribution.h @@ -14,9 +14,9 @@ /* begin namespace openfpga */ namespace openfpga { -void report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager, - const std::string& fname, - const size_t& max_hierarchy_level = 1); +int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager, + const std::string& fname, + const size_t& max_hierarchy_level = 1); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index c35017ba8..f4ac33ab5 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -14,6 +14,7 @@ /* Headers from fpgabitstream library */ #include "read_xml_arch_bitstream.h" #include "write_xml_arch_bitstream.h" +#include "report_arch_bitstream_distribution.h" #include "openfpga_naming.h" @@ -165,4 +166,41 @@ int write_io_mapping(const OpenfpgaContext& openfpga_ctx, return status; } +/******************************************************************** + * A wrapper function to call the report_arch_bitstream_distribution() in FPGA bitstream + *******************************************************************/ +int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_file = cmd.option("file"); + + int status = CMD_EXEC_SUCCESS; + + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + + std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file)); + + /* Create directories */ + create_directory(src_dir_path); + + /* Default depth requirement, this is to limit the report size by default */ + int depth = 1; + CommandOptionId opt_depth = cmd.option("depth"); + if (true == cmd_context.option_enable(cmd, opt_depth)) { + depth = std::atoi(cmd_context.option_value(cmd, opt_depth).c_str()); + /* Error out if we have negative depth */ + if (0 > depth) { + VTR_LOG_ERROR("Invalid depth '%d' which should be 0 or a positive number!\n", + depth); + return CMD_EXEC_FATAL_ERROR; + } + } + + status = report_architecture_bitstream_distribution(openfpga_ctx.bitstream_manager(), + cmd_context.option_value(cmd, opt_file), + depth); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream.h b/openfpga/src/base/openfpga_bitstream.h index 2e438d56b..c04fb7656 100644 --- a/openfpga/src/base/openfpga_bitstream.h +++ b/openfpga/src/base/openfpga_bitstream.h @@ -27,6 +27,9 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, int write_io_mapping(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 3599bcac5..80b4d8263 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -72,6 +72,40 @@ ShellCommandId add_openfpga_build_arch_bitstream_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("report_bitstream_distribution"); + + /* Add an option '--file' */ + CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the bitstream distribution"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--depth' */ + CommandOptionId opt_depth = shell_cmd.add_option("depth", false, "Specify the max. depth of blocks which will appear in report"); + shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command 'report_bitstream_distribution' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Report bitstream distribution"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, report_bitstream_distribution); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + /******************************************************************** * - Add a command to Shell environment: build_fabric_bitstream * - Add associated options @@ -187,6 +221,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell& shell) { cmd_dependency_build_arch_bitstream.push_back(shell_cmd_repack_id); ShellCommandId shell_cmd_build_arch_bitstream_id = add_openfpga_build_arch_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_build_arch_bitstream); + /******************************** + * Command 'report_bitstream_distribution' + */ + /* The 'report_bitstream_distribution' command should NOT be executed before 'build_architecture_bitstream' */ + std::vector cmd_dependency_report_bitstream_distribution; + cmd_dependency_build_arch_bitstream.push_back(shell_cmd_build_arch_bitstream_id); + add_openfpga_report_bitstream_distribution_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_report_bitstream_distribution); + /******************************** * Command 'build_fabric_bitstream' */ From c4ecc9ee7cf35fad710e6f61eca2d4a8f1daf07c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 11:44:01 -0600 Subject: [PATCH 259/352] [Tool] Patch data type of report bitstream distribution command-line option --- openfpga/src/base/openfpga_bitstream_command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 80b4d8263..39545d12f 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -90,7 +90,7 @@ ShellCommandId add_openfpga_report_bitstream_distribution_command(openfpga::Shel /* Add an option '--depth' */ CommandOptionId opt_depth = shell_cmd.add_option("depth", false, "Specify the max. depth of blocks which will appear in report"); - shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT); + shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_STRING); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); From 24f83f00588663a2ea6aced7c9dbe47ea52476c7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 11:54:33 -0600 Subject: [PATCH 260/352] [Doc] Update documentation about the new command 'report_bitstream_distribution' --- .../bitstream_distribution_file.rst | 50 +++++++++++++++++++ docs/source/manual/file_formats/index.rst | 2 + .../fpga_bitstream_commands.rst | 18 +++++++ 3 files changed, 70 insertions(+) create mode 100644 docs/source/manual/file_formats/bitstream_distribution_file.rst diff --git a/docs/source/manual/file_formats/bitstream_distribution_file.rst b/docs/source/manual/file_formats/bitstream_distribution_file.rst new file mode 100644 index 000000000..a1f3282d2 --- /dev/null +++ b/docs/source/manual/file_formats/bitstream_distribution_file.rst @@ -0,0 +1,50 @@ +.. _file_format_bitstream_distribution_file: + +Bitstream Distribution File (.xml) +---------------------------------- + +The bitstream distribution file aims to show + +- The total number of configuration bits under each block +- The number of configuration bits per block + +An example of design constraints is shown as follows. + +.. code-block:: xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +.. option:: name="" + + The block name represents the instance name which you can find in the fabric netlists + +.. option:: number_of_bits="" + + The total number of configuration bits in this block diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst index d1a77e2d0..7ed213012 100644 --- a/docs/source/manual/file_formats/index.rst +++ b/docs/source/manual/file_formats/index.rst @@ -23,3 +23,5 @@ OpenFPGA widely uses XML format for interchangable files fabric_key io_mapping_file + + bitstream_distribution_file diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index fbe10e033..a63717e15 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -87,4 +87,22 @@ write_io_mapping Show verbose log +report_bitstream_distribution +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Output the bitstream distribution to a file + + .. option:: --file or -f + + Specify the file name where the bitstream distribution will be outputted to. + See file formats in :ref:`file_format_bitstream_distribution_file`. + + .. option:: --depth or -d + + Specify the maximum depth of the block which should appear in the block + + .. option:: --verbose + + Show verbose log + From 7dc7c1b4f5576779361791296188a49d456c1c1c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 12:05:47 -0600 Subject: [PATCH 261/352] [Script] Add example openfpga shell script showing how to use 'report_bitstream_distribution' command --- ...tream_distribution_example_script.openfpga | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga new file mode 100644 index 000000000..7fd9666f0 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga @@ -0,0 +1,54 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --absorb_buffer_luts off + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enabled frame view creation to save runtime and memory +# Note that this is turned on when bitstream generation +# is the ONLY purpose of the flow!!! +build_fabric --compress_routing --frame_view #--verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.txt --format plain_text +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Report bitstream distribution to a file +report_bitstream_distribution ${OPENFPGA_REPORT_BITSTREAM_DISTRIBUTION_OPTIONS} + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 2baf3ddd2f9e25ba86f6c0a2905abaf331e84e95 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 12:06:24 -0600 Subject: [PATCH 262/352] [Test] Add test cases for 'report_bitstream_distribution' command --- .../custom_depth/config/task.conf | 33 +++++++++++++++++++ .../default_depth/config/task.conf | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/custom_depth/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/default_depth/config/task.conf diff --git a/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/custom_depth/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/custom_depth/config/task.conf new file mode 100644 index 000000000..ad24a1dd3 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/custom_depth/config/task.conf @@ -0,0 +1,33 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_report_bitstream_distribution_options=--file bitstream_distribution.xml --depth 2 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] diff --git a/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/default_depth/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/default_depth/config/task.conf new file mode 100644 index 000000000..fcbcb6a63 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/report_bitstream_distribution/default_depth/config/task.conf @@ -0,0 +1,33 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/report_bitstream_distribution_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_report_bitstream_distribution_options=--file bitstream_distribution.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] From c33ca464dc87035742fefce10e0361ebfee42348 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 7 May 2021 12:06:46 -0600 Subject: [PATCH 263/352] [Test] Deploy new tests to regression test --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index 1f1eac786..58858e0b9 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -28,3 +28,7 @@ run-task fpga_bitstream/overload_mux_default_path --debug --show_thread_logs echo -e "Testing outputting I/O mapping result to file"; run-task fpga_bitstream/write_io_mapping --debug --show_thread_logs + +echo -e "Testing report bitstream distribution to file"; +run-task fpga_bitstream/report_bitstream_distribution/default_depth --debug --show_thread_logs +run-task fpga_bitstream/report_bitstream_distribution/custom_depth --debug --show_thread_logs From b6b98a75b8ca10c01f0317b4ebf23076a398ef8f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 May 2021 13:03:40 -0600 Subject: [PATCH 264/352] [Doc] Add example circuit model about multi-mode flip-flops; Separate data-path FF circuit model and configuration-chain FF circuit model; --- .../arch_lang/circuit_model_examples.rst | 75 ++++++++- .../figures/multi_mode_ff_circuit_model.svg | 152 ++++++++++++++++++ docs/source/overview/tech_highlights.rst | 11 +- 3 files changed, 225 insertions(+), 13 deletions(-) create mode 100644 docs/source/manual/arch_lang/figures/multi_mode_ff_circuit_model.svg diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index a7a6dba97..32bddd841 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -963,16 +963,15 @@ This example shows: .. note:: If the embedded harden logic are driven partially by LUT outputs, users may use the :ref:`file_formats_bitstream_setting` to gaurantee correct bitstream generation for the LUTs. - -Flip-Flops -~~~~~~~~~~ +Datapath Flip-Flops +~~~~~~~~~~~~~~~~~~~ Template ```````` .. code-block:: xml - + @@ -987,16 +986,14 @@ Template .. note:: FPGA-Verilog/SPICE currently support only one clock domain in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1. -.. option:: +.. option:: type="ff" - - ``type="ccff|ff"`` Specify the type of a flip-flop. ``ff`` is a regular flip-flop while ``ccff`` denotes a configuration-chain flip-flop + ``ff`` is a regular flip-flop to be used in datapath logic, e.g., a configurable logic block. .. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``. .. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist. -.. note:: In a valid FPGA architecture, users should provide at least either a ``ccff`` or ``sram`` circuit model, so that the configurations can loaded to core logic. - .. _circuit_model_dff_example: D-type Flip-Flop @@ -1029,6 +1026,68 @@ This example shows: - The flip-flop has ``set`` and ``reset`` functionalities - The flip-flop port names defined differently in standard cell library and VPR architecture. The ``lib_name`` capture the port name defined in standard cells, while ``prefix`` capture the port name defined in ``pb_type`` of VPR architecture file +.. _circuit_model_multi_mode_ff_example: + +Multi-mode Flip-Flop +```````````````````` + +:numref:`fig_multi_mode_ff_circuit_model` illustrates an example of a flip-flop which can be operate in different modes. + +.. _fig_multi_mode_ff_circuit_model: + +.. figure:: ./figures/multi_mode_ff_circuit_model.svg + :scale: 100% + :alt: Multi-mode flip-flop example + + An example of a flip-flop which can be operate in different modes + +The code describing this FF is: + +.. code-block:: xml + + + + + + + + + +This example shows: + - A multi-mode flip-flop which is defined in a Verilog netlist ``frac_ff.v`` and a SPICE netlist ``frac_ff.sp`` + - The flip-flop has a ``reset`` pin which can be either active-low or active-high, depending on the mode selection pin ``MODE``. + - The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`). + - The flip-flop port names defined differently in standard cell library and VPR architecture. The ``lib_name`` capture the port name defined in standard cells, while ``prefix`` capture the port name defined in ``pb_type`` of VPR architecture file + +Configuration Chain Flip-Flop +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Template +```````` + +.. code-block:: xml + + + + + + + + + + +.. note:: The circuit designs of configurable memory elements are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-Verilog/SPICE requires users to provide their customized FF Verilog/SPICE/Verilog netlists. A sample Verilog/SPICE netlist of FF can be found in the directory SpiceNetlists in the released package. + + The information of input and output buffer should be clearly specified according to the customized SPICE netlist! The existence of input/output buffers will influence the decision in creating SPICE testbenches, which may leads to larger errors in power analysis. + +.. note:: FPGA-Verilog/SPICE currently support only one clock domain for any configuration protocols in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1. + +.. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``. + +.. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist. + +.. note:: In a valid FPGA architecture, users should provide at least either a ``ccff`` or ``sram`` circuit model, so that the configurations can loaded to core logic. + .. _circuit_model_ccff_example: Regular Configuration-chain Flip-flop diff --git a/docs/source/manual/arch_lang/figures/multi_mode_ff_circuit_model.svg b/docs/source/manual/arch_lang/figures/multi_mode_ff_circuit_model.svg new file mode 100644 index 000000000..de4016044 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/multi_mode_ff_circuit_model.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 18:52:28 +0000 + + multi_mode_ff + + Layer 1 + + + + + + + + + FF + + + + + D + + + + + CLK + + + + + + + + + + + + + + + + + + Q + + + + + RST + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Multi-mode FF + + + + + Q + + + + + D + + + + + MODE + + + + + CLK + + + + + RST_OP + + + + + diff --git a/docs/source/overview/tech_highlights.rst b/docs/source/overview/tech_highlights.rst index 95521cc29..c0d71fd15 100644 --- a/docs/source/overview/tech_highlights.rst +++ b/docs/source/overview/tech_highlights.rst @@ -42,15 +42,16 @@ Supported Circuit Designs +-----------------+--------------+-----------+-----------------------------------------------------+ | | Configurable | No | Yes | - :ref:`circuit_model_config_latch_example` | | | Memory | | | - :ref:`circuit_model_sram_blwl_example` | -| | | | - :ref:`circuit_model_dff_example` | | | | | - :ref:`circuit_model_ccff_example` | | | | | - :ref:`circuit_model_ccff_enable_example` | | | | | - :ref:`circuit_model_ccff_scanable_example` | +-----------------+--------------+-----------+-----------------------------------------------------+ -| Block RAM | No | Yes | - **Any size** | -| | | | - Single-port | -| | | | - Dual-port | -| | | | - Fracturable | +| Data Memory | No | Yes | - **Any size** | +| | | | - :ref:`circuit_model_dff_example` | +| | | | - :ref:`circuit_model_multi_mode_ff_example` | +| | | | - Single-port Block RAM | +| | | | - Dual-port Block RAM | +| | | | - Multi-mode Block RAM | +-----------------+--------------+-----------+-----------------------------------------------------+ | | Arithmetic | No | Yes | - **Any size** | | | Units | | | - Multiplier | From 21a18069a12a4941aab7511b65ae7c4ee252756f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 May 2021 14:50:55 -0600 Subject: [PATCH 265/352] [Doc] Add example circuit about dual-port RAMs to documentation; Updated technical highlights by providing links to the examples --- .../arch_lang/circuit_model_examples.rst | 84 ++++- ...i_mode_dpram128x8_memory_circuit_model.svg | 342 ++++++++++++++++++ ...e_mode_dpram128x8_memory_circuit_model.svg | 104 ++++++ docs/source/overview/tech_highlights.rst | 4 +- 4 files changed, 531 insertions(+), 3 deletions(-) create mode 100644 docs/source/manual/arch_lang/figures/multi_mode_dpram128x8_memory_circuit_model.svg create mode 100644 docs/source/manual/arch_lang/figures/single_mode_dpram128x8_memory_circuit_model.svg diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index 32bddd841..ca5c9e419 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -284,6 +284,8 @@ This example shows: SRAMs ~~~~~ +.. note:: OpenFPGA does not auto-generate any netlist for SRAM cells. Users should define the HDL modeling in external netlists and ensure consistency to physical designs. + Template ```````` @@ -966,6 +968,8 @@ This example shows: Datapath Flip-Flops ~~~~~~~~~~~~~~~~~~~ +.. note:: OpenFPGA does not auto-generate any netlist for datapath flip-flops. Users should define the HDL modeling in external netlists and ensure consistency to physical designs. + Template ```````` @@ -1036,7 +1040,7 @@ Multi-mode Flip-Flop .. _fig_multi_mode_ff_circuit_model: .. figure:: ./figures/multi_mode_ff_circuit_model.svg - :scale: 100% + :scale: 150% :alt: Multi-mode flip-flop example An example of a flip-flop which can be operate in different modes @@ -1062,6 +1066,8 @@ This example shows: Configuration Chain Flip-Flop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. note:: OpenFPGA does not auto-generate any netlist for configuration chain flip-flops. Users should define the HDL modeling in external netlists and ensure consistency to physical designs. + Template ```````` @@ -1206,6 +1212,8 @@ The code describing this FF is: Hard Logics ~~~~~~~~~~~ +.. note:: OpenFPGA does not auto-generate any netlist for the hard logics. Users should define the HDL modeling in external netlists and ensure consistency to physical designs. + Template ```````` @@ -1248,6 +1256,78 @@ Full Adder +This example shows: + - A 1-bit full adder which is defined in a Verilog netlist ``adder.v`` and a SPICE netlist ``adder.sp`` + - The adder has three 1-bit inputs, i.e., ``a``, ``b`` and ``cin``, and two 2-bit outputs, i.e., ``cout``, ``sumout``. + + +.. _circuit_model_single_mode_dpram_example: + +Dual Port Block RAM +``````````````````` + +.. figure:: ./figures/single_mode_dpram128x8_memory_circuit_model.svg + :scale: 150% + :alt: An example of a dual port block RAM with 128 addresses and 8-bit data width. + + An example of a dual port block RAM with 128 addresses and 8-bit data width. + +The code describing this block RAM is: + +.. code-block:: xml + + + + + + + + + + + + + + +This example shows: + - A 128x8 dual port RAM which is defined in a Verilog netlist ``dpram.v`` and a SPICE netlist ``dpram.sp`` + - The clock port of the RAM is controlled by a global signal (see details about global signal definition in :ref:`annotate_vpr_arch_physical_tile_annotation`). + +.. _circuit_model_multi_mode_dpram_example: + +Multi-mode Dual Port Block RAM +`````````````````````````````` + +.. figure:: ./figures/multi_mode_dpram128x8_memory_circuit_model.svg + :scale: 150% + :alt: An example of a multi-mode dual port block RAM with 128 addresses and 8-bit data width. + + An example of a dual port block RAM which can operate in two modes: 128x8 and 256x4. + +The code describing this block RAM is: + +.. code-block:: xml + + + + + + + + + + + + + + + +This example shows: + - A fracturable dual port RAM which is defined in a Verilog netlist ``frac_dpram.v`` and a SPICE netlist ``frac_dpram.sp`` + - The dual port RAM can operate in two modes: (1) 128 addresses with 8-bit data width; (2) 256 addresses with 4-bit data width + - The clock port of the RAM is controlled by a global signal (see details about global signal definition in :ref:`annotate_vpr_arch_physical_tile_annotation`). + - The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`). + Routing Wire Segments ~~~~~~~~~~~~~~~~~~~~~ @@ -1314,6 +1394,8 @@ This example shows I/O pads ~~~~~~~~ +.. note:: OpenFPGA does not auto-generate any netlist for I/O cells. Users should define the HDL modeling in external netlists and ensure consistency to physical designs. + Template ```````` diff --git a/docs/source/manual/arch_lang/figures/multi_mode_dpram128x8_memory_circuit_model.svg b/docs/source/manual/arch_lang/figures/multi_mode_dpram128x8_memory_circuit_model.svg new file mode 100644 index 000000000..ff02de2fc --- /dev/null +++ b/docs/source/manual/arch_lang/figures/multi_mode_dpram128x8_memory_circuit_model.svg @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 20:15:49 +0000 + + multi_mode_dual_port_bram 1 + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + clock + + + + + raddr[7:0] + + + + + waddr[7:0] + + + + + wen + + + + + ren + + + + + data_in[7:0] + + + + + data_out[7:0] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mode + + + + + + + + + + + + + + + + clock + + + + + raddr[6:0] + + + + + waddr[6:0] + + + + + wen + + + + + ren + + + + + data_in[7:0] + + + + + data_out[7:0] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mode + + + + + + + + â€1’ + + + + + + + + + + + + + clock + + + + + raddr[7:0] + + + + + waddr[7:0] + + + + + wen + + + + + ren + + + + + data_in[3:0] + + + + + data_out[3:0] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mode + + + + + + + + â€0’ + + + + + Operating mode 2: Dual port 256 + x + 4 RAM + + + + + Operating mode 1: Dual port 128x8 RAM + + + + + Schematic: Multi-mode dual port 128x8/256x4 RAM + + + + + + + + + + + + + diff --git a/docs/source/manual/arch_lang/figures/single_mode_dpram128x8_memory_circuit_model.svg b/docs/source/manual/arch_lang/figures/single_mode_dpram128x8_memory_circuit_model.svg new file mode 100644 index 000000000..458155c98 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/single_mode_dpram128x8_memory_circuit_model.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 19:57:04 +0000 + + single_mode_dual_port_bram + + Layer 1 + + + + + + + + + + + clock + + + + + raddr[6:0] + + + + + waddr[6:0] + + + + + wen + + + + + ren + + + + + data_in[7:0] + + + + + data_out[7:0] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/overview/tech_highlights.rst b/docs/source/overview/tech_highlights.rst index c0d71fd15..461be231c 100644 --- a/docs/source/overview/tech_highlights.rst +++ b/docs/source/overview/tech_highlights.rst @@ -50,8 +50,8 @@ Supported Circuit Designs | | | | - :ref:`circuit_model_dff_example` | | | | | - :ref:`circuit_model_multi_mode_ff_example` | | | | | - Single-port Block RAM | -| | | | - Dual-port Block RAM | -| | | | - Multi-mode Block RAM | +| | | | - :ref:`circuit_model_single_mode_dpram_example` | +| | | | - :ref:`circuit_model_multi_mode_dpram_example` | +-----------------+--------------+-----------+-----------------------------------------------------+ | | Arithmetic | No | Yes | - **Any size** | | | Units | | | - Multiplier | From 9b40e74e2555c80f0e0e2d1d5449d3d4b8e4ba68 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 May 2021 15:24:50 -0600 Subject: [PATCH 266/352] [Doc] Add example circuit models for multipliers and update technical highlight with links to the examples --- .../arch_lang/circuit_model_examples.rst | 63 +++++ .../figures/full_adder_1bit_circuit_model.svg | 76 ++++++ .../multi_mode_mult8x8_circuit_model.svg | 249 ++++++++++++++++++ .../single_mode_mult8x8_circuit_model.svg | 66 +++++ docs/source/overview/tech_highlights.rst | 5 +- 5 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 docs/source/manual/arch_lang/figures/full_adder_1bit_circuit_model.svg create mode 100644 docs/source/manual/arch_lang/figures/multi_mode_mult8x8_circuit_model.svg create mode 100644 docs/source/manual/arch_lang/figures/single_mode_mult8x8_circuit_model.svg diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index ca5c9e419..7113be1c0 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -1242,6 +1242,13 @@ Template Full Adder `````````` +.. figure:: ./figures/full_adder_1bit_circuit_model.svg + :scale: 200% + :alt: An example of a 1-bit full adder + + An example of a 1-bit full adder. + +The code describing the 1-bit full adder is: .. code-block:: xml @@ -1260,6 +1267,62 @@ This example shows: - A 1-bit full adder which is defined in a Verilog netlist ``adder.v`` and a SPICE netlist ``adder.sp`` - The adder has three 1-bit inputs, i.e., ``a``, ``b`` and ``cin``, and two 2-bit outputs, i.e., ``cout``, ``sumout``. +.. _circuit_model_single_mode_mult8x8_example: + +Multiplier +`````````` + +.. figure:: ./figures/single_mode_mult8x8_circuit_model.svg + :scale: 200% + :alt: An example of a 8-bit multiplier. + + An example of a 8-bit multiplier. + +The code describing the multiplier is: + +.. code-block:: xml + + + + + + + + + + +This example shows: + - A 8-bit multiplier which is defined in a Verilog netlist ``dsp.v`` and a SPICE netlist ``dsp.sp`` + +.. _circuit_model_multi_mode_mult8x8_example: + +Multi-mode Multiplier +````````````````````` + +.. figure:: ./figures/multi_mode_mult8x8_circuit_model.svg + :scale: 200% + :alt: An example of a 8-bit multiplier which can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier + + An example of a 8-bit multiplier which can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier + +The code describing the multiplier is: + +.. code-block:: xml + + + + + + + + + + + +This example shows: + - A multi-mode 8-bit multiplier which is defined in a Verilog netlist ``dsp.v`` and a SPICE netlist ``dsp.sp`` + - The multi-mode multiplier can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier + - The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`). .. _circuit_model_single_mode_dpram_example: diff --git a/docs/source/manual/arch_lang/figures/full_adder_1bit_circuit_model.svg b/docs/source/manual/arch_lang/figures/full_adder_1bit_circuit_model.svg new file mode 100644 index 000000000..dc7ff3837 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/full_adder_1bit_circuit_model.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 20:57:16 +0000 + + 1-bit full adder + + Layer 1 + + + + + adder + + + + + + cin + + + + + a + + + + + b + + + + + + + + + + + + + + sumout + + + + + + + + cout + + + + + + + + diff --git a/docs/source/manual/arch_lang/figures/multi_mode_mult8x8_circuit_model.svg b/docs/source/manual/arch_lang/figures/multi_mode_mult8x8_circuit_model.svg new file mode 100644 index 000000000..8c9b5f2a1 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/multi_mode_mult8x8_circuit_model.svg @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 21:09:05 +0000 + + multi_mode_mult_8x8 + + Layer 1 + + + + + + + + + + + + + MULT + 8x8 + + + + + a[7:0] + + + + + b[7:0] + + + + + + + + + + + + + + out[15:0] + + + + + + + + + + + + + MULT + 4x4 + [0] + + + + + a[7:4] + + + + + b[7:4] + + + + + + + + + + + + + + out[15:8] + + + + + + + + + + + + + MULT + 4x4 + [1] + + + + + a[3:0] + + + + + b[3:0] + + + + + + + + + + + + + + out[7:0] + + + + + + + + + + + Operating mode 1: Dual 4x4 multiplier + + + + + + + + mode + + + + + Schematic: multi-mode 8x8 multiplier + + + + + + + + + + + MULT + 8x8 + + + + + a[7:0] + + + + + b[7:0] + + + + + + + + + + + + + + out[15:0] + + + + + + + + + + + Operating mode 2: 8x8 multiplier + + + + + + + + mode=â€0’ + + + + + + + + + + + + + + + + mode=â€1’ + + + + + + + + diff --git a/docs/source/manual/arch_lang/figures/single_mode_mult8x8_circuit_model.svg b/docs/source/manual/arch_lang/figures/single_mode_mult8x8_circuit_model.svg new file mode 100644 index 000000000..41ac61370 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/single_mode_mult8x8_circuit_model.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-05-24 21:09:05 +0000 + + single_mode_mult_8x8 + + Layer 1 + + + + + MULT + 8x8 + + + + + a[7:0] + + + + + b[7:0] + + + + + + + + + + + + + + out[15:0] + + + + + + + + + + + diff --git a/docs/source/overview/tech_highlights.rst b/docs/source/overview/tech_highlights.rst index 461be231c..10e7dc1af 100644 --- a/docs/source/overview/tech_highlights.rst +++ b/docs/source/overview/tech_highlights.rst @@ -54,8 +54,9 @@ Supported Circuit Designs | | | | - :ref:`circuit_model_multi_mode_dpram_example` | +-----------------+--------------+-----------+-----------------------------------------------------+ | | Arithmetic | No | Yes | - **Any size** | -| | Units | | | - Multiplier | -| | | | - :ref:`circuit_model_full_adder_example` | +| | Units | | | - :ref:`circuit_model_full_adder_example` | +| | | | - :ref:`circuit_model_single_mode_mult8x8_example` | +| | | | - :ref:`circuit_model_multi_mode_mult8x8_example` | +-----------------+--------------+-----------+-----------------------------------------------------+ | I/O | No | Yes | - :ref:`circuit_model_gpio_example` | | | | | - Bi-directional buffer | From 16ae23f33e12f261cd5f900ce9a7545a3ea38f79 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 May 2021 16:26:59 -0600 Subject: [PATCH 267/352] [Doc] Update notes about compilation guidelines --- docs/source/tutorials/getting_started/compile.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/getting_started/compile.rst b/docs/source/tutorials/getting_started/compile.rst index 3f2b45a2d..c7a5e74fc 100644 --- a/docs/source/tutorials/getting_started/compile.rst +++ b/docs/source/tutorials/getting_started/compile.rst @@ -24,7 +24,7 @@ In general, please follow the steps to compile .. note:: cmake3.12+ is recommended to compile OpenFPGA with GUI -.. note:: Recommand to use ``make -j`` to accelerate the compilation +.. note:: Recommand to use ``make -j`` to accelerate the compilation, where ```` denotes the number of cores to be used in compilation. .. note:: VPR's GUI requires gtk-3, and can be enabled with ``cmake .. -DVPR_USE_EZGL=on`` From 1fd399736d6c04a0ada47ce9dc98f8704d65e568 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 27 May 2021 10:26:20 -0600 Subject: [PATCH 268/352] [Tool] Patch FPGA-SDC to consider time unit in global port timing constraints --- openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp | 15 +++++++++++---- openfpga/src/fpga_sdc/pnr_sdc_global_port.h | 1 + openfpga/src/fpga_sdc/pnr_sdc_writer.cpp | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp index 8f7c92046..156f78ff1 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp @@ -20,6 +20,7 @@ /* Headers from openfpgautil library */ #include "openfpga_port.h" #include "openfpga_digest.h" +#include "openfpga_scale.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" @@ -59,6 +60,7 @@ void print_pnr_sdc_clock_port(std::fstream& fp, *******************************************************************/ static void print_pnr_sdc_global_clock_ports(std::fstream& fp, + const float& time_unit, const ModuleManager& module_manager, const ModuleId& top_module, const FabricGlobalPortInfo& fabric_global_port_info, @@ -103,7 +105,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp, print_pnr_sdc_clock_port(fp, port_to_constrain, - clock_period); + clock_period / time_unit); } } } @@ -118,6 +120,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp, *******************************************************************/ static void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, + const float& time_unit, const float& operating_critical_path_delay, const ModuleManager& module_manager, const ModuleId& top_module, @@ -144,7 +147,7 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, print_pnr_sdc_clock_port(fp, port_to_constrain, - clock_period); + clock_period / time_unit); } } } @@ -161,6 +164,7 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, * In general, we do not recommend to do this *******************************************************************/ void print_pnr_sdc_global_ports(const std::string& sdc_dir, + const float& time_unit, const ModuleManager& module_manager, const ModuleId& top_module, const FabricGlobalPortInfo& global_ports, @@ -183,12 +187,15 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir, /* Generate the descriptions*/ print_sdc_file_header(fp, std::string("Clock contraints for PnR")); - print_pnr_sdc_global_clock_ports(fp, + /* Print time unit for the SDC file */ + print_sdc_timescale(fp, time_unit_to_string(time_unit)); + + print_pnr_sdc_global_clock_ports(fp, time_unit, module_manager, top_module, global_ports, sim_setting); if (true == constrain_non_clock_port) { - print_pnr_sdc_global_non_clock_ports(fp, + print_pnr_sdc_global_non_clock_ports(fp, time_unit, 1./sim_setting.default_operating_clock_frequency(), module_manager, top_module, global_ports); diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h index 15808e623..ae12a5a21 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h @@ -18,6 +18,7 @@ namespace openfpga { void print_pnr_sdc_global_ports(const std::string& sdc_dir, + const float& time_unit, const ModuleManager& module_manager, const ModuleId& top_module, const FabricGlobalPortInfo& global_ports, diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp index 5fb902010..1bd025871 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp @@ -336,6 +336,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, /* Constrain global ports */ if (true == sdc_options.constrain_global_port()) { print_pnr_sdc_global_ports(sdc_options.sdc_dir(), + sdc_options.time_unit(), module_manager, top_module, global_ports, sim_setting, sdc_options.constrain_non_clock_global_port()); From ae6a46cd60249ccc8ae75ac0b53de57969bc5c94 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 15:37:49 -0600 Subject: [PATCH 269/352] [Tool] Add a new command write_full_testbench which outputs self-testable full testbench which loads external bitstream file; Currently only support configuration chain without fast configuration technique --- openfpga/src/base/openfpga_verilog.cpp | 50 ++ openfpga/src/base/openfpga_verilog.h | 3 + .../src/base/openfpga_verilog_command.cpp | 63 +++ openfpga/src/fpga_verilog/verilog_api.cpp | 64 ++- openfpga/src/fpga_verilog/verilog_api.h | 14 + .../fpga_verilog/verilog_top_testbench.cpp | 429 ++++++++++++++++++ .../src/fpga_verilog/verilog_top_testbench.h | 17 + .../src/fpga_verilog/verilog_writer_utils.cpp | 10 +- .../src/fpga_verilog/verilog_writer_utils.h | 3 +- 9 files changed, 648 insertions(+), 5 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index ad92228f1..6a3afdefd 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -119,4 +119,54 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the full testbench generator of FPGA-Verilog + *******************************************************************/ +int write_full_testbench(OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_bitstream = cmd.option("bitstream"); + CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog + * Keep it independent from any other outside data structures + */ + VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); + options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_print_top_testbench(true); + options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); + + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + + return fpga_verilog_full_testbench(openfpga_ctx.module_graph(), + openfpga_ctx.bitstream_manager(), + openfpga_ctx.fabric_bitstream(), + g_vpr_ctx.atom(), + g_vpr_ctx.placement(), + pin_constraints, + cmd_context.option_value(cmd, opt_bitstream), + openfpga_ctx.io_location_map(), + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.simulation_setting(), + openfpga_ctx.arch().config_protocol, + options); +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 096039aab..20ce5d858 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -21,6 +21,9 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_full_testbench(OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 946f0e2bf..4518c0634 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -122,6 +122,59 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_full_testbench"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* Add an option '--bitstream'*/ + CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "Specify the bitstream to be loaded in the testbench"); + shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING); + + /* Add an option '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric HDL netlist"); + shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); + + /* Add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(pcf_opt, "pcf"); + shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); + + /* Add an option '--reference_benchmark_file_path'*/ + CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); + shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); + + /* Add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + + /* Add an option '--include_signal_init' */ + shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches"); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an FPGA fabric"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_full_testbench); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + void add_openfpga_verilog_commands(openfpga::Shell& shell) { /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); @@ -148,6 +201,16 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { add_openfpga_write_verilog_testbench_command(shell, openfpga_verilog_cmd_class, verilog_testbench_dependent_cmds); + + /******************************** + * Command 'write_full_testbench' + */ + /* The command 'write_full_testbench' should NOT be executed before 'build_fabric' */ + std::vector full_testbench_dependent_cmds; + full_testbench_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_full_testbench_command(shell, + openfpga_verilog_cmd_class, + full_testbench_dependent_cmds); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 46a81c96e..fa0980eea 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -32,8 +32,7 @@ #include "verilog_api.h" /* begin namespace openfpga */ -namespace openfpga -{ +namespace openfpga { /******************************************************************** * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation @@ -253,4 +252,65 @@ int fpga_verilog_testbench(const ModuleManager &module_manager, return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on full testbench generation + * This function will generate + * - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated + ********************************************************************/ +int fpga_verilog_full_testbench(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const FabricBitstream &fabric_bitstream, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const PinConstraints& pin_constraints, + const std::string& bitstream_file, + const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const SimulationSetting &simulation_setting, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write Verilog full testbenches for FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + /* Create directories */ + create_directory(src_dir_path); + + /* Output preprocessing flags for HDL simulations */ + print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), + options); + + /* Generate full testbench for verification, including configuration phase and operating phase */ + std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + print_verilog_full_testbench(module_manager, + bitstream_manager, fabric_bitstream, + circuit_lib, + config_protocol, + fabric_global_port_info, + atom_ctx, place_ctx, + pin_constraints, + bitstream_file, + io_location_map, + netlist_annotation, + netlist_name, + top_testbench_file_path, + simulation_setting, + options); + + /* Generate a Verilog file including all the netlists that have been generated */ + print_verilog_testbench_include_netlists(src_dir_path, + netlist_name, + options.fabric_netlist_file_path(), + options.reference_benchmark_file_path()); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 6c3ec190e..f3f0b8321 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -57,6 +57,20 @@ int fpga_verilog_testbench(const ModuleManager& module_manager, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); +int fpga_verilog_full_testbench(const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, + const std::string& bitstream_file, + const IoLocationMap& io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const CircuitLibrary& circuit_lib, + const SimulationSetting& simulation_parameters, + const ConfigProtocol& config_protocol, + const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index d58a2c730..c87073c67 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -59,6 +59,10 @@ constexpr char* TOP_TB_OP_CLOCK_PORT_PREFIX = "operating_clk_"; constexpr char* TOP_TB_PROG_CLOCK_PORT_NAME = "prog_clock"; constexpr char* TOP_TB_INOUT_REG_POSTFIX = "_reg"; constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg"; +constexpr char* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH"; +constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH"; +constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem"; +constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index"; constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; @@ -1930,6 +1934,164 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp, } } +/******************************************************************** + * Print stimulus for a FPGA fabric with a configuration chain protocol + * where configuration bits are programming in serial (one by one) + * Task list: + * 1. For clock signal, we should create voltage waveforms for two types of clock signals: + * a. operation clock + * b. programming clock + * 2. For Set/Reset, we reset the chip after programming phase ends + * and before operation phase starts + * 3. For input/output clb nets (mapped to I/O grids), + * we should create voltage waveforms only after programming phase + *******************************************************************/ +static +void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + + /* Find the longest bitstream */ + size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), regional_bitstream_max_size); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), fabric_bitstream.num_regions()); + + /* Initial value should be the first configuration bits + * In the rest of programming cycles, + * configuration bits are fed at the falling edge of programming clock. + * We do not care the value of scan_chain head during the first programming cycle + * It is reset anyway + */ + ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); + BasicPort config_chain_head_port = module_manager.module_port(top_module, cc_head_port_id); + std::vector initial_values(config_chain_head_port.get_width(), 0); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Configuration chain default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(config_chain_head_port, initial_values, true); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + + +/******************************************************************** + * Generate the stimuli for the full testbench + * The simulation consists of two phases: configuration phase and operation phase + * Configuration bits are loaded serially. + * This is actually what we do for a physical FPGA + *******************************************************************/ +static +void print_verilog_full_testbench_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const e_config_protocol_type& config_protocol_type, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { + + /* Branch on the type of configuration protocol */ + switch (config_protocol_type) { + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + print_verilog_full_testbench_configuration_chain_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + bitstream_manager, fabric_bitstream); + break; + case CONFIG_MEM_MEMORY_BANK: + break; + case CONFIG_MEM_FRAME_BASED: + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + exit(1); + } +} + + /******************************************************************** * Connect proper stimuli to the reset port * This function is designed to drive the reset port of a benchmark module @@ -2017,6 +2179,8 @@ void print_verilog_top_testbench_check(std::fstream& fp, } /******************************************************************** + * TODO: This top function will be deprecated!!! The only top function is + * print_verilog_full_testbench() * The top-level function to generate a testbench, in order to verify: * 1. Configuration phase of the FPGA fabric, where the bitstream is * loaded to the configuration protocol of the FPGA fabric @@ -2275,4 +2439,269 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, fp.close(); } +/******************************************************************** + * The top-level function to generate a full testbench, in order to verify: + * 1. Configuration phase of the FPGA fabric, where the bitstream is + * loaded to the configuration protocol of the FPGA fabric + * 2. Operating phase of the FPGA fabric, where input stimuli are + * fed to the I/Os of the FPGA fabric + * +----------+ + * | FPGA | +------------+ + * +----->| Fabric |------>| | + * | | | | | + * | +----------+ | | + * | | Output | + * random_input_vectors -----+ | Vector |---->Functional correct? + * | | Comparator | + * | +-----------+ | | + * | | Input | | | + * +----->| Benchmark |----->| | + * +-----------+ +------------+ + * + *******************************************************************/ +int print_verilog_full_testbench(const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, + const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, + const std::string& bitstream_file, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, + const std::string& verilog_fname, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options) { + + bool fast_configuration = options.fast_configuration(); + bool explicit_port_mapping = options.explicit_port_mapping(); + + std::string timer_message = std::string("Write autocheck testbench for FPGA top-level Verilog netlist for '") + circuit_name + std::string("'"); + + /* Start time count */ + vtr::ScopedStartFinishTimer timer(timer_message); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + check_file_stream(verilog_fname.c_str(), fp); + + /* Generate a brief description on the Verilog file*/ + std::string title = std::string("FPGA Verilog full testbench for top-level netlist of design: ") + circuit_name; + print_verilog_file_header(fp, title); + + /* Find the top_module */ + ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + + /* Preparation: find all the clock ports */ + std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + + /* Preparation: find all the reset/set ports for programming usage */ + std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + + /* Identify if we can apply fast configuration */ + bool apply_fast_configuration = fast_configuration; + if ( (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) + && (true == fast_configuration)) { + VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is turned off\n"); + apply_fast_configuration = false; + } + bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), + apply_fast_configuration, + global_prog_reset_ports, + global_prog_set_ports, + bitstream_manager, fabric_bitstream); + + /* Start of testbench */ + print_verilog_top_testbench_ports(fp, module_manager, top_module, + atom_ctx, netlist_annotation, + clock_port_names, + pin_constraints, + simulation_parameters, config_protocol, + circuit_name); + + /* Find the clock period */ + float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); + float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency()); + float max_op_clock_period = 0.; + for (const SimulationClockId& clock_id : simulation_parameters.clocks()) { + max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id))); + } + + /* Estimate the number of configuration clock cycles */ + size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(), + apply_fast_configuration, + bit_value_to_skip, + bitstream_manager, + fabric_bitstream); + + /* Generate stimuli for general control signals */ + print_verilog_top_testbench_generic_stimulus(fp, + simulation_parameters, + num_config_clock_cycles, + prog_clock_period, + default_op_clock_period, + VERILOG_SIM_TIMESCALE); + + /* Generate stimuli for programming interface */ + print_verilog_top_testbench_configuration_protocol_stimulus(fp, + config_protocol.type(), + module_manager, top_module, + prog_clock_period, + VERILOG_SIM_TIMESCALE); + + /* Identify the stimulus for global reset/set for programming purpose: + * - If only reset port is seen we turn on Reset + * - If only set port is seen we turn on Reset + * - If both reset and set port is defined, + * we pick the one which is consistent with the bit value to be skipped + */ + bool active_global_prog_reset = false; + bool active_global_prog_set = false; + + if (!global_prog_reset_ports.empty()) { + active_global_prog_reset = true; + } + + if (!global_prog_set_ports.empty()) { + active_global_prog_set = true; + } + + /* Ensure that at most only one of the two switches is activated */ + if ( (true == active_global_prog_reset) + && (true == active_global_prog_set) ) { + /* If we will skip logic '0', we will activate programming reset */ + active_global_prog_reset = !bit_value_to_skip; + /* If we will skip logic '1', we will activate programming set */ + active_global_prog_set = bit_value_to_skip; + } + + /* Generate stimuli for global ports or connect them to existed signals */ + print_verilog_top_testbench_global_ports_stimuli(fp, + module_manager, top_module, + pin_constraints, + global_ports, + simulation_parameters, + active_global_prog_reset, + active_global_prog_set); + + /* Instanciate FPGA top-level module */ + print_verilog_testbench_fpga_instance(fp, module_manager, top_module, + std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), + explicit_port_mapping); + + /* Connect I/Os to benchmark I/Os or constant driver */ + print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, + atom_ctx, place_ctx, io_location_map, + netlist_annotation, + std::string(), + std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), + (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); + + /* Instanciate input benchmark */ + print_verilog_top_testbench_benchmark_instance(fp, + circuit_name, + atom_ctx, + netlist_annotation, + explicit_port_mapping); + + /* Print tasks used for loading bitstreams */ + print_verilog_top_testbench_load_bitstream_task(fp, + config_protocol.type(), + module_manager, top_module); + + /* load bitstream to FPGA fabric in a configuration phase */ + print_verilog_full_testbench_bitstream(fp, + bitstream_file, + config_protocol.type(), + apply_fast_configuration, + bit_value_to_skip, + module_manager, top_module, + bitstream_manager, fabric_bitstream); + + /* Add signal initialization: + * Bypass writing codes to files due to the autogenerated codes are very large. + */ + if (true == options.include_signal_init()) { + print_verilog_testbench_signal_initialization(fp, + std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), + circuit_lib, + module_manager, + top_module); + } + + + /* Add stimuli for reset, set, clock and iopad signals */ + print_verilog_top_testbench_reset_stimuli(fp, + atom_ctx, + netlist_annotation, + module_manager, + global_ports, + pin_constraints, + clock_port_names); + print_verilog_testbench_random_stimuli(fp, atom_ctx, + netlist_annotation, + module_manager, + global_ports, + pin_constraints, + clock_port_names, + std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), + std::vector(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1))); + + /* Add output autocheck */ + print_verilog_testbench_check(fp, + std::string(AUTOCHECKED_SIMULATION_FLAG), + std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), + std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), + std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), + std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), + std::string(TOP_TESTBENCH_ERROR_COUNTER), + atom_ctx, + netlist_annotation, + clock_port_names, + std::string(TOP_TB_OP_CLOCK_PORT_NAME)); + + /* Add autocheck for configuration phase */ + print_verilog_top_testbench_check(fp, + std::string(AUTOCHECKED_SIMULATION_FLAG), + std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + std::string(TOP_TESTBENCH_ERROR_COUNTER)); + + /* Find simulation time */ + float simulation_time = find_simulation_time_period(VERILOG_SIM_TIMESCALE, + num_config_clock_cycles, + 1./simulation_parameters.programming_clock_frequency(), + simulation_parameters.num_clock_cycles(), + 1./simulation_parameters.default_operating_clock_frequency()); + + + /* Add Icarus requirement: + * Always ceil the simulation time so that we test a sufficient length of period!!! + */ + print_verilog_timeout_and_vcd(fp, + std::string(ICARUS_SIMULATOR_FLAG), + std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), + std::string(circuit_name + std::string("_formal.vcd")), + std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), + std::string(TOP_TESTBENCH_ERROR_COUNTER), + std::ceil(simulation_time)); + + + /* Testbench ends*/ + print_verilog_module_end(fp, std::string(circuit_name) + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)); + + /* Close the file stream */ + fp.close(); + + return 0; +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index ca36d61e9..1704d0dd5 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -42,6 +42,23 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, const SimulationSetting& simulation_parameters, const VerilogTestbenchOption& options); +int print_verilog_full_testbench(const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, + const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, + const std::string& bitstream_file, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, + const std::string& verilog_fname, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index fbf69c16d..9a55968b0 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -724,14 +724,20 @@ std::string generate_verilog_constant_values(const std::vector& const_va * Generate a verilog port with a deposite of constant values ********************************************************************/ std::string generate_verilog_port_constant_values(const BasicPort& output_port, - const std::vector& const_values) { + const std::vector& const_values, + const bool& is_register) { std::string port_str; /* Must check: the port width matches */ VTR_ASSERT( const_values.size() == output_port.get_width() ); port_str = generate_verilog_port(VERILOG_PORT_CONKT, output_port); - port_str += " = "; + if (is_register) { + port_str += " <= "; + } else { + VTR_ASSERT_SAFE(!is_register); + port_str += " = "; + } port_str += generate_verilog_constant_values(const_values); return port_str; } diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.h b/openfpga/src/fpga_verilog/verilog_writer_utils.h index 61f13385e..09a5dba7a 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.h +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.h @@ -108,7 +108,8 @@ std::string generate_verilog_constant_values(const std::vector& const_va const bool& short_constant = true); std::string generate_verilog_port_constant_values(const BasicPort& output_port, - const std::vector& const_values); + const std::vector& const_values, + const bool& is_register = false); void print_verilog_wire_constant_values(std::fstream& fp, const BasicPort& output_port, From 51ca62a464a7315353927027281cf2f465435426 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 15:48:59 -0600 Subject: [PATCH 270/352] [Script] Add example script for write_full_testbench command --- ...ite_full_testbench_example_script.openfpga | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga new file mode 100644 index 000000000..6764208e8 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 1e9f6eb4391644e17f25c12204dbac74bfb09267 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 15:53:27 -0600 Subject: [PATCH 271/352] [Test] update configuration chain test to use new testbench --- .../full_testbench/configuration_chain/config/task.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf index 7ae2d1334..11f45da04 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf @@ -16,7 +16,7 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml From 9bcaa820ae850b785f21ba5b4f0d12749041f254 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 16:18:07 -0600 Subject: [PATCH 272/352] [Doc] Update documentation for the new command 'write_full_testbench' --- .../manual/file_formats/fabric_bitstream.rst | 2 +- .../fpga_verilog_commands.rst | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index 11faca959..92e11f24e 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -5,7 +5,7 @@ Fabric-dependent Bitstream .. _file_formats_fabric_bitstream_plain_text: -Plain text (.txt) +Plain text (.bit) ~~~~~~~~~~~~~~~~~ This file format is designed to be directly loaded to an FPGA fabric. diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index 11c64b45f..c22d5aa73 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -87,3 +87,39 @@ write_verilog_testbench .. option:: --explicit_port_mapping Use explicit port mapping when writing the Verilog netlists + +write_full_testbench +~~~~~~~~~~~~~~~~~~~~~~~ + + Write the full testbench for FPGA fabric in Verilog format + + .. option:: --file or -f + + The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` + + .. option:: --bitstream + + The bitstream file to be loaded to the full testbench, which should be in the same file format that OpenFPGA can outputs (See detailes in :ref:`file_formats_fabric_bitstream_plain_text`). For example, ``--bitstream and2.bit`` + + .. option:: --fabric_netlist_file_path + + Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v`` + + .. option:: --reference_benchmark_file_path + + Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v`` + + .. option:: --pin_constraints_file or -pcf + + Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` + Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. + + .. option:: --explicit_port_mapping + + Use explicit port mapping when writing the Verilog netlists + + .. option:: --include_signal_init + + Output signal initialization to Verilog testbench to smooth convergence in HDL simulation + + From b83d8826fb87739b464401979d15937199175799 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 16:54:13 -0600 Subject: [PATCH 273/352] [Doc] Update documentation on the testbench organization/waveforms --- .../figures/full_testbench_block_diagram.svg | 102 + .../figures/full_testbench_waveform.svg | 2160 +++++++++++++++++ .../verilog_testbench_organization.png | Bin 290654 -> 0 bytes docs/source/manual/fpga_verilog/testbench.rst | 20 +- 4 files changed, 2276 insertions(+), 6 deletions(-) create mode 100644 docs/source/manual/fpga_verilog/figures/full_testbench_block_diagram.svg create mode 100644 docs/source/manual/fpga_verilog/figures/full_testbench_waveform.svg delete mode 100644 docs/source/manual/fpga_verilog/figures/verilog_testbench_organization.png diff --git a/docs/source/manual/fpga_verilog/figures/full_testbench_block_diagram.svg b/docs/source/manual/fpga_verilog/figures/full_testbench_block_diagram.svg new file mode 100644 index 000000000..4e528898b --- /dev/null +++ b/docs/source/manual/fpga_verilog/figures/full_testbench_block_diagram.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-06-03 22:42:19 +0000 + + block_diagram + + + Layer 1 + + + + + Bitstream file + + + + + + + + block_diagram + + + + + FPGA + Fabric + + + + + + + User’s + Design + + + + + + + Output + Checker + + + + + Input stimulus + + + + + + + + + + + + + + Number of + errors + + + + + FPGA output vectors + + + + + Expected output vectors + + + + + + + + + + + diff --git a/docs/source/manual/fpga_verilog/figures/full_testbench_waveform.svg b/docs/source/manual/fpga_verilog/figures/full_testbench_waveform.svg new file mode 100644 index 000000000..3d8e8acb3 --- /dev/null +++ b/docs/source/manual/fpga_verilog/figures/full_testbench_waveform.svg @@ -0,0 +1,2160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-06-03 22:42:19 +0000 + + waveform + + + Layer 1 + + + Operating Phase + + + + + Configuration Phase + + + + + + + + + + + + + + + + waves_0 + + lanes_0 + + gmarks_0 + + + gmark_0_0 + + + + gmark_1_0 + + + + gmark_2_0 + + + + gmark_3_0 + + + + gmark_4_0 + + + + gmark_5_0 + + + + gmark_6_0 + + + + gmark_7_0 + + + + gmark_8_0 + + + + gmark_9_0 + + + + gmark_10_0 + + + + gmark_11_0 + + + + gmark_12_0 + + + + + + Text + + 0 + + + + Text + + 1 + + + + Text + + 2 + + + + Text + + 3 + + + + Text + + 4 + + + + Text + + 5 + + + + Text + + 6 + + + + Text + + 7 + + + + Text + + 8 + + + + Text + + 9 + + + + Text + + 10 + + + + Text + + 11 + + + + Text + + 12 + + + + + + wavelane_0_0 + + Text + + prog_clk + + + + wavelane_draw_0_0 + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + + + wavelane_1_0 + + Text + + prog_rst + + + + wavelane_draw_1_0 + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 1m0 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + + + wavelane_2_0 + + Text + + clk + + + + wavelane_draw_2_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0m0 + + + + + + 000 + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + Pclk + + + + + + + + + nclk + + + + + + + + wavelane_3_0 + + Text + + rst + + + + wavelane_draw_3_0 + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 111 + + + + + + 1m0 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + + + wavelane_4_0 + + Text + + prog_input + + + + wavelane_draw_4_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0mv-3 + + + + + + + + + + + + vvv-3 + + + + + + + + + + + + vvv-3 + + + + + + + + + + + + vvv-3 + + + + + + + + + + + + vvv-3 + + + + + + + + + + + + vvv-3 + + + + + + + + + + + + vm0-3 + + + + + + + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + Text + + Bitstream + + + + + + wavelane_5_0 + + Text + + Input stimulus + + + + wavelane_draw_5_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0mv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + vvv-4 + + + + + + + + + + + + Text + + Random vectors + + + + + + wavelane_6_0 + + Text + + FPGA outputs + + + + wavelane_draw_6_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0mv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + Text + + FPGA stimulis response + + + + + + wavelane_7_0 + + Text + + Expected outputs + + + + wavelane_draw_7_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0mv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + vvv-5 + + + + + + + + + + + + Text + + Benchmark stimulis response + + + + + + wavelane_8_0 + + Text + + Errors + + + + wavelane_draw_8_0 + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 000 + + + + + + 0mv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + vvv-6 + + + + + + + + + + + + Text + + Number of errors + + + + + + wavegaps_0 + + wavegap_0_0 + + gap + + + + + + + + + + + + + wavegap_1_0 + + gap + + + + + + + + + + + + + wavegap_2_0 + + gap + + + + + + + + + + + + + wavegap_3_0 + + gap + + + + + + + + + + + + + wavegap_4_0 + + gap + + + + + + + + + + + + + wavegap_5_0 + + gap + + + + + + + + + + + + + wavegap_6_0 + + gap + + + + + + + + + + + + + wavegap_7_0 + + gap + + + + + + + + + + + + + wavegap_8_0 + + gap + + + + + + + + + + + + + + + + + diff --git a/docs/source/manual/fpga_verilog/figures/verilog_testbench_organization.png b/docs/source/manual/fpga_verilog/figures/verilog_testbench_organization.png deleted file mode 100644 index 06f6d58fa5f4d7ab37289cb91448092464ec2102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290654 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

`})bP1+w#SIC%HU&g@-*z!u(Eri^gelzgge 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

@aNoW@T&Jdq>cpzE8fDN=8DId@hYOc)g`@ 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 z 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

v(0U&o?1}({jF{6#m!YQ{?}H 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 Date: Thu, 3 Jun 2021 17:08:08 -0600 Subject: [PATCH 274/352] [Script] Update write_full_testbench example script to support custom device layout in VPR --- .../write_full_testbench_example_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga index 6764208e8..2a001ad30 100644 --- a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga @@ -1,6 +1,6 @@ # Run VPR for the 'and' design #--write_rr_graph example_rr_graph.xml -vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route ${OPENFPGA_VPR_DEVICE_LAYOUT} # Read OpenFPGA architecture definition read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} From ebe30fc0703fcd670d2eacf12c07d8522352f09f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 3 Jun 2021 17:08:33 -0600 Subject: [PATCH 275/352] [Test] Deploy write full testbench to multi-head configuration chain test case --- .../full_testbench/configuration_chain/config/task.conf | 1 + .../multi_region_configuration_chain/config/task.conf | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf index 11f45da04..f11b117cd 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf @@ -19,6 +19,7 @@ fpga_flow=yosys_vpr openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf index eff60d97e..ebc47d3b6 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf @@ -16,10 +16,10 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=2x2 +openfpga_vpr_device_layout=--device 2x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From adb18d28b8f77538071340cac45d76a3a95de297 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 10:37:28 -0600 Subject: [PATCH 276/352] [Tool] Remove unused arguments --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index c87073c67..13cfb52af 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1953,7 +1953,6 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, - const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); @@ -2078,7 +2077,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, fast_configuration, bit_value_to_skip, module_manager, top_module, - bitstream_manager, fabric_bitstream); + fabric_bitstream); break; case CONFIG_MEM_MEMORY_BANK: break; From 98308133c1f558bc35e973ee2f964861d064f19a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:24:05 -0600 Subject: [PATCH 277/352] [Tool] Add configuration skip capability to top testbench which loads external bitstream file --- .../fpga_verilog/verilog_top_testbench.cpp | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 13cfb52af..fb88e2bbf 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -63,6 +63,8 @@ constexpr char* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH"; constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH"; constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem"; constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index"; +constexpr char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit"; +constexpr char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits"; constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; @@ -1983,7 +1985,12 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << std::endl; fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - + + BasicPort bit_skip_reg(TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME, 1); + print_verilog_comment(fp, "----- Registers used for fast configuration logic -----"); + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, bit_skip_reg) << ";" << std::endl; + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; @@ -2001,6 +2008,62 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << ";"; fp << std::endl; + std::vector bit_skip_values(bit_skip_reg.get_width(), fast_configuration ? 1 : 0); + fp << "\t"; + fp << generate_verilog_port_constant_values(bit_skip_reg, bit_skip_values, true); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << "for (" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = 0; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " < `" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " + 1; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = " << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " + 1)"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "if ("; + fp << generate_verilog_constant_values(std::vector(fabric_bitstream.num_regions(), bit_value_to_skip)); + fp << " == "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "]"; + fp << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t\t"; + fp << "if ("; + fp << generate_verilog_constant_values(std::vector(bit_skip_reg.get_width(), 1)); + fp << " == "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bit_skip_reg) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t\t\t"; + fp << "end"; + fp << std::endl; + + fp << "\t\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t\t"; + fp << generate_verilog_port_constant_values(bit_skip_reg, std::vector(bit_skip_reg.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "\t\t"; + fp << "end"; + fp << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + fp << "end"; fp << std::endl; From 81048d3698ec78d911239ddbefbc7f1e17c62d64 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:26:39 -0600 Subject: [PATCH 278/352] [Tool] Add option '--fast_configuration' to 'write_full_testbench' command --- openfpga/src/base/openfpga_verilog.cpp | 2 ++ openfpga/src/base/openfpga_verilog_command.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 6a3afdefd..6cfb9879a 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -130,6 +130,7 @@ int write_full_testbench(OpenfpgaContext& openfpga_ctx, CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_fast_configuration = cmd.option("fast_configuration"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -141,6 +142,7 @@ int write_full_testbench(OpenfpgaContext& openfpga_ctx, options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration)); options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_top_testbench(true); diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 4518c0634..431eac47f 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -155,6 +155,9 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell Date: Fri, 4 Jun 2021 11:28:10 -0600 Subject: [PATCH 279/352] [Script] Update openfpga shell script with fast configuration option --- .../write_full_testbench_example_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga index 2a001ad30..8a87a0a08 100644 --- a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit ${OPENFPGA_FAST_CONFIGURATION} # Write the SDC files for PnR backend # - Turn on every options here From aa4e1f5f9a228f0c83769f171d3851aaea3cd6d2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:29:43 -0600 Subject: [PATCH 280/352] [Test] Update test case which uses write_full_testbench openfpga shell script --- .../full_testbench/configuration_chain/config/task.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf index f11b117cd..1f818415a 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf @@ -20,6 +20,7 @@ openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scrip openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 2068291de03695a57f1e3d98b14c81024b3c6345 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:32:49 -0600 Subject: [PATCH 281/352] [Test] Now deploy the 'write_full_testbench' openfpga shell script to all the configuration chain test cases --- .../configuration_chain_config_enable_scff/config/task.conf | 4 +++- .../configuration_chain_use_reset/config/task.conf | 4 +++- .../configuration_chain_use_resetb/config/task.conf | 4 +++- .../configuration_chain_use_set/config/task.conf | 4 +++- .../configuration_chain_use_set_reset/config/task.conf | 4 +++- .../configuration_chain_use_setb/config/task.conf | 4 +++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_config_enable_scff/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_config_enable_scff/config/task.conf index 8fd922fd9..a554331f3 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_config_enable_scff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_config_enable_scff/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 1*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_cfgscff_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_reset/config/task.conf index 9d7ea2d8d..0707f4df2 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_resetb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_resetb/config/task.conf index 4efa817a1..627e7a9ec 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_resetb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_resetb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_resetb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set/config/task.conf index 37a1eb75b..e452a2371 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set_reset/config/task.conf index 94acf3ed8..da327282e 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_set_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_setb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_setb/config/task.conf index d3290d175..1706a4e4e 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_setb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain_use_setb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_setb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From ec203d3a5cef7a5408952691ea481aea328b1a5c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:35:23 -0600 Subject: [PATCH 282/352] [Test] Deploy 'write_full_testbench' openfpga shell script to all the fast configuration chain test cases --- .../full_testbench/fast_configuration_chain/config/task.conf | 4 +++- .../fast_configuration_chain_use_set/config/task.conf | 4 +++- .../smart_fast_configuration_chain/config/task.conf | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf index 1967bd2a4..71dbae458 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain_use_set/config/task.conf index 51f2344fe..10d5bfd62 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_chain_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_chain/config/task.conf index 4fac7ac49..56f90daef 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_chain/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 5f96d440ec63a57bc2ab01dc2dbd332b302c94ae Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 11:48:05 -0600 Subject: [PATCH 283/352] [Test] Deploy 'write_full_testbench' openfpga shell script to multi-headed configuration chain with auto-tuned fast configuration --- .../config/task.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_chain/config/task.conf index ed7db9ae5..a5f85fc2b 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_chain/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 059e74b4efda3b04f207d7afcbc6fd0aa8030c99 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 15:17:00 -0600 Subject: [PATCH 284/352] [Doc] Add --fast configuration option to documentation for 'write_full_testbench' --- .../openfpga_commands/fpga_verilog_commands.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index c22d5aa73..8b559c698 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -114,6 +114,12 @@ write_full_testbench Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. + .. option:: --fast_configuration + + Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal. + + .. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration. + .. option:: --explicit_port_mapping Use explicit port mapping when writing the Verilog netlists From 061f83242966a56e98d0b63d198491b01faef403 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 16:23:40 -0600 Subject: [PATCH 285/352] [Tool] Enable fast configuration when writing fabric bitstream --- openfpga/src/base/openfpga_bitstream.cpp | 3 + .../src/base/openfpga_bitstream_command.cpp | 3 + .../src/fpga_bitstream/fast_configuration.cpp | 128 ++++++++++++++++++ .../src/fpga_bitstream/fast_configuration.h | 30 ++++ .../write_text_fabric_bitstream.cpp | 33 ++++- .../write_text_fabric_bitstream.h | 3 + 6 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 openfpga/src/fpga_bitstream/fast_configuration.cpp create mode 100644 openfpga/src/fpga_bitstream/fast_configuration.h diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index f4ac33ab5..78e0cbddd 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -91,6 +91,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_file = cmd.option("file"); CommandOptionId opt_file_format = cmd.option("format"); + CommandOptionId opt_fast_config = cmd.option("fast_configuration"); /* Write fabric bitstream if required */ int status = CMD_EXEC_SUCCESS; @@ -119,7 +120,9 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(), openfpga_ctx.fabric_bitstream(), openfpga_ctx.arch().config_protocol, + openfpga_ctx.fabric_global_port_info(), cmd_context.option_value(cmd, opt_file), + cmd_context.option_enable(cmd, opt_fast_config), cmd_context.option_enable(cmd, opt_verbose)); } diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 39545d12f..a59d19adf 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -151,6 +151,9 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell + +/* Headers from vtrutil library */ +#include "vtr_log.h" +#include "vtr_assert.h" + +#include "fabric_global_port_info_utils.h" +#include "fast_configuration.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Identify if fast configuration is applicable base on the availability + * of programming reset and programming set ports of the FPGA fabric + *******************************************************************/ +bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports) { + /* Preparation: find all the reset/set ports for programming usage */ + std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + + /* Identify if we can apply fast configuration */ + if (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { + VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is not applicable\n"); + return false; + } + + return true; +} + +/******************************************************************** + * Decide if we should use reset or set signal to acheive fast configuration + * - If only one type signal is specified, we use that type + * For example, only reset signal is defined, we will use reset + * - If both are defined, pick the one that will bring bigger reduction + * i.e., larger number of configuration bits can be skipped + *******************************************************************/ +bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, + const FabricGlobalPortInfo& global_ports, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { + /* Preparation: find all the reset/set ports for programming usage */ + std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + + /* Early exit conditions */ + if (!global_prog_reset_ports.empty() && global_prog_set_ports.empty()) { + return false; + } else if (!global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { + return true; + } + + /* If both types of ports are not defined, the fast configuration is not applicable */ + VTR_ASSERT(!global_prog_set_ports.empty() && !global_prog_reset_ports.empty()); + bool bit_value_to_skip = false; + + VTR_LOG("Both reset and set ports are defined for programming controls, selecting the best-fit one...\n"); + + size_t num_ones_to_skip = 0; + size_t num_zeros_to_skip = 0; + + /* Branch on the type of configuration protocol */ + switch (config_protocol_type) { + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* We can only skip the ones/zeros at the beginning of the bitstream */ + /* Count how many logic '1' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + break; + } + VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); + num_ones_to_skip++; + } + /* Count how many logic '0' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + break; + } + VTR_ASSERT(false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); + num_zeros_to_skip++; + } + break; + } + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_FRAME_BASED: { + /* Count how many logic '1' and logic '0' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + num_zeros_to_skip++; + } else { + VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); + num_ones_to_skip++; + } + } + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + exit(1); + } + + VTR_LOG("Using reset will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_zeros_to_skip / (float) fabric_bitstream.num_bits(), + num_zeros_to_skip, fabric_bitstream.num_bits()); + + VTR_LOG("Using set will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_ones_to_skip / (float) fabric_bitstream.num_bits(), + num_ones_to_skip, fabric_bitstream.num_bits()); + + /* By default, we prefer to skip zeros (when the numbers are the same */ + if (num_ones_to_skip > num_zeros_to_skip) { + VTR_LOG("Will use set signal in fast configuration\n"); + bit_value_to_skip = true; + } else { + VTR_LOG("Will use reset signal in fast configuration\n"); + } + + return bit_value_to_skip; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fast_configuration.h b/openfpga/src/fpga_bitstream/fast_configuration.h new file mode 100644 index 000000000..eb161d1b2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/fast_configuration.h @@ -0,0 +1,30 @@ +#ifndef FAST_CONFIGURATION_H +#define FAST_CONFIGURATION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "fabric_global_port_info.h" +#include "config_protocol.h" +#include "bitstream_manager.h" +#include "fabric_bitstream.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports); + +bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, + const FabricGlobalPortInfo& global_ports, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 3fa604de1..663e679d3 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -16,6 +16,7 @@ #include "openfpga_naming.h" +#include "fast_configuration.h" #include "bitstream_manager_utils.h" #include "fabric_bitstream_utils.h" #include "write_text_fabric_bitstream.h" @@ -118,6 +119,8 @@ int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& fast_configuration, + const bool& bit_value_to_skip, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream) { int status = 0; @@ -125,7 +128,18 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); - for (size_t ibit = 0; ibit < regional_bitstream_max_size; ++ibit) { + /* For fast configuration, the bitstream size counts from the first bit '1' */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + } + VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); + + VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size, + num_bits_to_skip, regional_bitstream_max_size); + + for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { for (const auto& region_bitstream : regional_bitstreams) { fp << region_bitstream[ibit]; } @@ -214,7 +228,9 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const std::string& fname, + const bool& fast_configuration, const bool& verbose) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { @@ -230,6 +246,19 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage check_file_stream(fname.c_str(), fp); + bool apply_fast_configuration = is_fast_configuration_applicable(global_ports); + if (fast_configuration && apply_fast_configuration != fast_configuration) { + VTR_LOG_WARN("Disable fast configuration even it is enabled by user\n"); + } + + bool bit_value_to_skip = false; + if (apply_fast_configuration) { + bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), + global_ports, + bitstream_manager, + fabric_bitstream); + } + /* Output fabric bitstream to the file */ int status = 0; switch (config_protocol.type()) { @@ -241,6 +270,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage break; case CONFIG_MEM_SCAN_CHAIN: status = write_config_chain_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, + bit_value_to_skip, bitstream_manager, fabric_bitstream); break; diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h index 9582a185c..17811f439 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h @@ -9,6 +9,7 @@ #include "bitstream_manager.h" #include "fabric_bitstream.h" #include "config_protocol.h" +#include "fabric_global_port_info.h" /******************************************************************** * Function declaration @@ -20,7 +21,9 @@ namespace openfpga { int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const std::string& fname, + const bool& fast_configuration, const bool& verbose); } /* end namespace openfpga */ From e9fa44cc2520d89f7392f45d221f5f9ff29e6c71 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 16:24:56 -0600 Subject: [PATCH 286/352] [Tool] Add fast configuration to the write bitstream command in example shell script --- .../write_full_testbench_example_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga index 8a87a0a08..612249a15 100644 --- a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.bit --format plain_text +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text ${OPENFPGA_FAST_CONFIGURATION} # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist From 6e69c2d70a1f69aa960e293feec7f95a64327ab2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 16:34:55 -0600 Subject: [PATCH 287/352] [Tool] Patch fast configuration in full Verilog testbench generator --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index fb88e2bbf..cdc820e87 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -22,6 +22,7 @@ #include "simulation_utils.h" #include "openfpga_atom_netlist_utils.h" +#include "fast_configuration.h" #include "fabric_bitstream_utils.h" #include "fabric_global_port_info_utils.h" @@ -1955,6 +1956,7 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, + const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); @@ -1964,8 +1966,15 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp /* Find the longest bitstream */ size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + /* For fast configuration, the bitstream size counts from the first bit '1' */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + } + VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); + /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), regional_bitstream_max_size); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), regional_bitstream_max_size - num_bits_to_skip); print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), fabric_bitstream.num_regions()); /* Initial value should be the first configuration bits @@ -2140,6 +2149,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, fast_configuration, bit_value_to_skip, module_manager, top_module, + bitstream_manager, fabric_bitstream); break; case CONFIG_MEM_MEMORY_BANK: From d98be9f87b907956b135ab71649a96a26d68c6b5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 16:45:00 -0600 Subject: [PATCH 288/352] [Tool] Remove icarus requirement on vcd writing in Verilog testbenches; Since vcd writing commands are standard Verilog --- .../verilog_formal_random_top_testbench.cpp | 1 - openfpga/src/fpga_verilog/verilog_testbench_utils.cpp | 11 ++--------- openfpga/src/fpga_verilog/verilog_testbench_utils.h | 1 - openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 2 -- 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index 848970a30..9ed4a8138 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -359,7 +359,6 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, /* Add Icarus requirement */ print_verilog_timeout_and_vcd(fp, - std::string(ICARUS_SIMULATOR_FLAG), std::string(circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)), std::string(circuit_name + std::string("_formal.vcd")), std::string(FORMAL_TB_SIM_START_PORT_NAME), diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 3329d33cf..994d6f280 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -300,7 +300,6 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, * Note that: these codes are tuned for Icarus simulator!!! *******************************************************************/ void print_verilog_timeout_and_vcd(std::fstream& fp, - const std::string& icarus_preprocessing_flag, const std::string& module_name, const std::string& vcd_fname, const std::string& simulation_start_counter_name, @@ -309,20 +308,14 @@ void print_verilog_timeout_and_vcd(std::fstream& fp, /* Validate the file stream */ valid_file_stream(fp); - /* The following verilog codes are tuned for Icarus */ - print_verilog_preprocessing_flag(fp, icarus_preprocessing_flag); - - print_verilog_comment(fp, std::string("----- Begin Icarus requirement -------")); + print_verilog_comment(fp, std::string("----- Begin output waveform to VCD file-------")); fp << "\tinitial begin" << std::endl; fp << "\t\t$dumpfile(\"" << vcd_fname << "\");" << std::endl; fp << "\t\t$dumpvars(1, " << module_name << ");" << std::endl; fp << "\tend" << std::endl; - /* Condition ends for the Icarus requirement */ - print_verilog_endif(fp); - - print_verilog_comment(fp, std::string("----- END Icarus requirement -------")); + print_verilog_comment(fp, std::string("----- END output waveform to VCD file -------")); /* Add an empty line as splitter */ fp << std::endl; diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index 0eb77bda9..807d25ae5 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -55,7 +55,6 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, const size_t& unused_io_value); void print_verilog_timeout_and_vcd(std::fstream& fp, - const std::string& icarus_preprocessing_flag, const std::string& module_name, const std::string& vcd_fname, const std::string& simulation_start_counter_name, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index cdc820e87..a5359f585 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2496,7 +2496,6 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, * Always ceil the simulation time so that we test a sufficient length of period!!! */ print_verilog_timeout_and_vcd(fp, - std::string(ICARUS_SIMULATOR_FLAG), std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), std::string(circuit_name + std::string("_formal.vcd")), std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), @@ -2758,7 +2757,6 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, * Always ceil the simulation time so that we test a sufficient length of period!!! */ print_verilog_timeout_and_vcd(fp, - std::string(ICARUS_SIMULATOR_FLAG), std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), std::string(circuit_name + std::string("_formal.vcd")), std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), From 70fb3a85dc08d0365719e3613f03b52cd55477c3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 17:23:10 -0600 Subject: [PATCH 289/352] [Tool] Patch fast configuration in bitstream writing --- .../fpga_bitstream/write_text_fabric_bitstream.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 663e679d3..9a637bc72 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -132,12 +132,11 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, size_t num_bits_to_skip = 0; if (true == fast_configuration) { num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); + VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size, + num_bits_to_skip, regional_bitstream_max_size); } - VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); - - VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size, - num_bits_to_skip, regional_bitstream_max_size); for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { for (const auto& region_bitstream : regional_bitstreams) { @@ -246,7 +245,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage check_file_stream(fname.c_str(), fp); - bool apply_fast_configuration = is_fast_configuration_applicable(global_ports); + bool apply_fast_configuration = is_fast_configuration_applicable(global_ports) && fast_configuration; if (fast_configuration && apply_fast_configuration != fast_configuration) { VTR_LOG_WARN("Disable fast configuration even it is enabled by user\n"); } From 27fa15603ace0281fef84083e384fa7fe498a455 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 18:17:47 -0600 Subject: [PATCH 290/352] [Tool] Patch test case due to changes in the template script --- .../multi_region_configuration_chain/config/task.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf index ebc47d3b6..dd4bea019 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain/config/task.conf @@ -20,6 +20,7 @@ openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scrip openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout=--device 2x2 +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From cf7addb1a6847fc24603cdaf37bab8bfb6988806 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 19:48:48 -0600 Subject: [PATCH 291/352] [Tool] Add heads to bitstream plain text file --- .../write_text_fabric_bitstream.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 9a637bc72..5be5d04cc 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -13,6 +13,7 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" +#include "openfpga_version.h" #include "openfpga_naming.h" @@ -24,6 +25,21 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * This function write header information to a bitstream file + *******************************************************************/ +static +void write_fabric_bitstream_text_file_head(std::fstream& fp) { + valid_file_stream(fp); + + auto end = std::chrono::system_clock::now(); + std::time_t end_time = std::chrono::system_clock::to_time_t(end); + + fp << "// Fabric bitstream" << std::endl; + fp << "// Version: " << openfpga::VERSION << std::endl; + fp << "// Date: " << std::ctime(&end_time) << std::endl; +} + /******************************************************************** * Write a configuration bit into a plain text file * The format depends on the type of configuration protocol @@ -138,6 +154,11 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, num_bits_to_skip, regional_bitstream_max_size); } + /* Output bitstream size information */ + fp << "// Bitstream length: " << regional_bitstream_max_size - num_bits_to_skip << std::endl; + fp << "// Bitstream width (LSB -> MSB): " << fabric_bitstream.num_regions() << std::endl; + + /* Output bitstream data */ for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { for (const auto& region_bitstream : regional_bitstreams) { fp << region_bitstream[ibit]; @@ -258,6 +279,9 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage fabric_bitstream); } + /* Write file head */ + write_fabric_bitstream_text_file_head(fp); + /* Output fabric bitstream to the file */ int status = 0; switch (config_protocol.type()) { From c30be6e95ee9ca4cf495868e6c627dd0d3dc06be Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 20:00:28 -0600 Subject: [PATCH 292/352] [Doc] Update documentation about the fast configuration for write bitstream command --- .../openfpga_commands/fpga_bitstream_commands.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index a63717e15..12c4d8ff5 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -69,6 +69,15 @@ write_fabric_bitstream Specify the file format [``plain_text`` | ``xml``]. By default is ``plain_text``. See file formats in :ref:`file_formats_fabric_bitstream_xml` and :ref:`file_formats_fabric_bitstream_plain_text`. + .. option:: --fast_configuration + + Reduce the bitstream size when outputing by skipping dummy configuration bits. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal. + + .. warning:: Fast configuration is only applicable to plain text file format! + + .. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration. + + .. option:: --verbose Show verbose log From 618b04568f09f21024551c9d27866b629a1bece7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 4 Jun 2021 20:07:42 -0600 Subject: [PATCH 293/352] [Tool] Remove unnecessary new line in bitstream file --- openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 5be5d04cc..1fb86c574 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -37,7 +37,7 @@ void write_fabric_bitstream_text_file_head(std::fstream& fp) { fp << "// Fabric bitstream" << std::endl; fp << "// Version: " << openfpga::VERSION << std::endl; - fp << "// Date: " << std::ctime(&end_time) << std::endl; + fp << "// Date: " << std::ctime(&end_time); } /******************************************************************** @@ -163,7 +163,9 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, for (const auto& region_bitstream : regional_bitstreams) { fp << region_bitstream[ibit]; } - fp << std::endl; + if (ibit < regional_bitstream_max_size - 1) { + fp << std::endl; + } } return status; From d644b8f22d7b2386fcf59e471f65c13f83c996cf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 11:55:11 -0600 Subject: [PATCH 294/352] [Tool] Support external bitstream file when generating full testbench for frame-based decoder --- .../write_text_fabric_bitstream.cpp | 37 ++++- .../fpga_verilog/verilog_top_testbench.cpp | 128 ++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 1fb86c574..0e8a435e7 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -215,15 +215,48 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + /* The address sizes and data input sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + size_t addr_size = fabric_bits_by_addr.begin()->first.size(); + size_t din_size = fabric_bits_by_addr.begin()->second.size(); + + /* Identify and output bitstream size information */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); + VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(), + num_bits_to_skip, fabric_bits_by_addr.size()); + } + + /* Output information about how to intepret the bitstream */ + fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl; + fp << "// Bitstream address size (LSB -> MSB): " << addr_size << std::endl; + fp << "// Bitstream data input size (LSB -> MSB): " << din_size << std::endl; + for (const auto& addr_din_pair : fabric_bits_by_addr) { + /* When fast configuration is enabled, + * the rule to skip any configuration bit should consider the whole data input values. + * Only all the bits in the din port match the value to be skipped, + * the programming cycle can be skipped! + */ + if (true == fast_configuration) { + if (addr_din_pair.second == std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { + continue; + } + } + /* Write address code */ fp << addr_din_pair.first; - fp << " "; /* Write data input */ for (const bool& din_value : addr_din_pair.second) { @@ -306,6 +339,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage break; case CONFIG_MEM_FRAME_BASED: status = write_frame_based_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, + bit_value_to_skip, fabric_bitstream); break; default: diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index a5359f585..951611c39 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2122,6 +2122,128 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } +/******************************************************************** + * Print stimulus for a FPGA fabric with a frame-based configuration protocol + * where configuration bits are programming in serial (one by one) + *******************************************************************/ +static +void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Reorganize the fabric bitstream by the same address across regions */ + FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + + /* For fast configuration, identify the final bitstream size to be used */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + } + VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); + + /* Feed address and data input pair one by one + * Note: the first cycle is reserved for programming reset + * We should give dummy values + */ + ModulePortId addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); + std::vector initial_addr_values(addr_port.get_width(), 0); + + ModulePortId din_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port = module_manager.module_port(top_module, din_port_id); + std::vector initial_din_values(din_port.get_width(), 0); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), addr_port.get_width() + din_port.get_width()); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Address port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(addr_port, initial_addr_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Data-input port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(din_port, initial_din_values); + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "{"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + fp << ", "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << "}"; + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} /******************************************************************** * Generate the stimuli for the full testbench @@ -2155,6 +2277,12 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, case CONFIG_MEM_MEMORY_BANK: break; case CONFIG_MEM_FRAME_BASED: + print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); + break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, From af298de12143acfbc9cbd6e85664f7ef56183e15 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 13:53:32 -0600 Subject: [PATCH 295/352] [Tool] Patch bugs in the full testbench writing using external bitstream file for frame-based configuration protocol --- openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp | 3 +-- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 0e8a435e7..57d8d92e1 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -240,8 +240,7 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, /* Output information about how to intepret the bitstream */ fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl; - fp << "// Bitstream address size (LSB -> MSB): " << addr_size << std::endl; - fp << "// Bitstream data input size (LSB -> MSB): " << din_size << std::endl; + fp << "// Bitstream width (LSB -> MSB):

" << std::endl; for (const auto& addr_din_pair : fabric_bits_by_addr) { /* When fast configuration is enabled, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 951611c39..20f3a5bcb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2191,6 +2191,11 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, fp << ";"; fp << std::endl; + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + fp << "end"; fp << std::endl; From a67196178e179b346c57c6e5e1dc820a1276d179 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 13:58:15 -0600 Subject: [PATCH 296/352] [Test] Now use 'write_full_testbench' in configuration frame test cases --- .../full_testbench/configuration_frame/config/task.conf | 4 +++- .../full_testbench/configuration_frame_ccff/config/task.conf | 4 +++- .../full_testbench/configuration_frame_scff/config/task.conf | 4 +++- .../configuration_frame_use_reset/config/task.conf | 4 +++- .../configuration_frame_use_resetb/config/task.conf | 4 +++- .../configuration_frame_use_set/config/task.conf | 4 +++- .../configuration_frame_use_set_reset/config/task.conf | 4 +++- .../configuration_frame_use_setb/config/task.conf | 4 +++- .../full_testbench/fast_configuration_frame/config/task.conf | 4 +++- .../fast_configuration_frame_use_set/config/task.conf | 4 +++- .../multi_region_configuration_frame/config/task.conf | 4 +++- .../smart_fast_configuration_frame/config/task.conf | 4 +++- .../config/task.conf | 4 +++- 13 files changed, 39 insertions(+), 13 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame/config/task.conf index aaee4c7c9..0389fee37 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_ccff/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_ccff/config/task.conf index 37d68988c..576a1888b 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_ccff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_ccff/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_ccff_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_scff/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_scff/config/task.conf index 2a8cded3f..7daaf775c 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_scff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_scff/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_scff_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_reset/config/task.conf index 40b3c6f9b..27b6005e8 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_resetb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_resetb/config/task.conf index d6f4a1812..3d3c4acdd 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_resetb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_resetb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_resetb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set/config/task.conf index 86edcefec..81d1067d9 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set_reset/config/task.conf index e91cbd103..0a19f0e50 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_set_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_setb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_setb/config/task.conf index 63baba79e..1247d8f78 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_setb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/configuration_frame_use_setb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_setb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame/config/task.conf index 14425886d..f9b1656f1 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame_use_set/config/task.conf index 2ee58fbf2..afd572370 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_configuration_frame_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_frame/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_frame/config/task.conf index 85771410c..b3c193558 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_frame/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_frame/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_frame_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_frame/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_frame/config/task.conf index d4a77cd79..38e2e9556 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_frame/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_configuration_frame/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_frame/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_frame/config/task.conf index 4f9b28e27..13da04cef 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_frame/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_configuration_frame/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_frame_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 0fee74100865bea508fcf3e87ccec542bad8fc7e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 14:22:35 -0600 Subject: [PATCH 297/352] [Doc] Update documentation on the minor changes on fabric bitstream file format --- .../manual/file_formats/fabric_bitstream.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index 92e11f24e..46a7b852a 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -63,7 +63,14 @@ The information depends on the type of configuration procotol. .. option:: frame_based - Multiple lines will be included, each of which is organized as
. + Multiple lines will be included, each of which is organized as ``
``. + The size of address line and data input bits are shown as a comment in the bitstream file, which eases the development of bitstream downloader. + For example + + .. code-block:: verilog + + // Bitstream width (LSB -> MSB):
+ Note that the address may include don't care bit which is denoted as ``x``. .. note:: OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches. @@ -72,10 +79,10 @@ The information depends on the type of configuration procotol. .. code-block:: xml - - + + ... - + .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. From 1a5902ca74758ad8436d94349170bc5d359efb54 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 14:32:56 -0600 Subject: [PATCH 298/352] [Tool] Bug fix in finding pruned bitstream for frame-based protocol when fast configuration is enabled --- openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp | 2 +- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 57d8d92e1..b887bd861 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -231,7 +231,7 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, /* Identify and output bitstream size information */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = fabric_bits_by_addr.size() - find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", 100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(), diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 20f3a5bcb..3b82e92c2 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2143,7 +2143,7 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, /* For fast configuration, identify the final bitstream size to be used */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = fabric_bits_by_addr.size() - find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); } VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); From ba75c18378277ff5e9882ef9e4374ec561f79841 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 17:40:07 -0600 Subject: [PATCH 299/352] [Tool] Now 'write_full_testbench' supports memory bank configuration protocol --- .../write_text_fabric_bitstream.cpp | 46 +++++- .../fpga_verilog/verilog_top_testbench.cpp | 146 ++++++++++++++++++ 2 files changed, 187 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index b887bd861..fdd27f649 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -181,20 +181,54 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, - const FabricBitstream& fabric_bitstream) { + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream) { int status = 0; MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + /* The address sizes and data input sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size(); + size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size(); + size_t din_size = fabric_bits_by_addr.begin()->second.size(); + + /* Identify and output bitstream size information */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); + VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", + 100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(), + num_bits_to_skip, fabric_bits_by_addr.size()); + } + + /* Output information about how to intepret the bitstream */ + fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl; + fp << "// Bitstream width (LSB -> MSB): "; + fp << ""; + fp << ""; + fp << ""; + fp << std::endl; + for (const auto& addr_din_pair : fabric_bits_by_addr) { + /* When fast configuration is enabled, + * the rule to skip any configuration bit should consider the whole data input values. + * Only all the bits in the din port match the value to be skipped, + * the programming cycle can be skipped! + */ + if (true == fast_configuration) { + if (addr_din_pair.second == std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { + continue; + } + } + /* Write BL address code */ fp << addr_din_pair.first.first; - fp << " "; - /* Write WL address code */ fp << addr_din_pair.first.second; - fp << " "; - /* Write data input */ for (const bool& din_value : addr_din_pair.second) { fp << din_value; @@ -334,6 +368,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage break; case CONFIG_MEM_MEMORY_BANK: status = write_memory_bank_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, + bit_value_to_skip, fabric_bitstream); break; case CONFIG_MEM_FRAME_BASED: diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 3b82e92c2..3a237160c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2122,6 +2122,147 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } +/******************************************************************** + * Print stimulus for a FPGA fabric with a memory bank configuration protocol + * where configuration bits are programming in serial (one by one) + *******************************************************************/ +static +void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Reorganize the fabric bitstream by the same address across regions */ + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + + /* For fast configuration, identify the final bitstream size to be used */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + } + VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); + + /* Feed address and data input pair one by one + * Note: the first cycle is reserved for programming reset + * We should give dummy values + */ + ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); + + ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); + + ModulePortId din_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port = module_manager.module_port(top_module, din_port_id); + std::vector initial_din_values(din_port.get_width(), 0); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Word-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Data-input port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(din_port, initial_din_values); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "{"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); + fp << ", "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); + fp << ", "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << "}"; + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + /******************************************************************** * Print stimulus for a FPGA fabric with a frame-based configuration protocol * where configuration bits are programming in serial (one by one) @@ -2280,6 +2421,11 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, fabric_bitstream); break; case CONFIG_MEM_MEMORY_BANK: + print_verilog_full_testbench_memory_bank_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); break; case CONFIG_MEM_FRAME_BASED: print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file, From 9556f994b4d291593d0bafdf3a4aab11887df73e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 17:49:40 -0600 Subject: [PATCH 300/352] [Test] Use 'write_full_testbench' in all the memory bank -related test cases --- .../full_testbench/fast_memory_bank/config/task.conf | 4 +++- .../full_testbench/fast_memory_bank_use_set/config/task.conf | 4 +++- .../basic_tests/full_testbench/memory_bank/config/task.conf | 4 +++- .../full_testbench/memory_bank_use_reset/config/task.conf | 4 +++- .../full_testbench/memory_bank_use_resetb/config/task.conf | 4 +++- .../full_testbench/memory_bank_use_set/config/task.conf | 4 +++- .../full_testbench/memory_bank_use_set_reset/config/task.conf | 4 +++- .../full_testbench/memory_bank_use_setb/config/task.conf | 4 +++- .../full_testbench/multi_region_memory_bank/config/task.conf | 3 ++- .../full_testbench/smart_fast_memory_bank/config/task.conf | 4 +++- .../smart_fast_multi_region_memory_bank/config/task.conf | 4 +++- 11 files changed, 32 insertions(+), 11 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank/config/task.conf index 5510c7a8c..c8789b46a 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank_use_set/config/task.conf index 1ceeb3384..03c0b97ed 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fast_memory_bank_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank/config/task.conf index 960cc0358..bd08da556 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_reset/config/task.conf index 88f00dd83..d20ef4ee8 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_resetb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_resetb/config/task.conf index 2db9c982f..502cd68ae 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_resetb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_resetb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_resetb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set/config/task.conf index 1b27c683c..33ea7546f 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_set_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set_reset/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set_reset/config/task.conf index 1e15dba22..52e103c6f 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set_reset/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_set_reset/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_setb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_setb/config/task.conf index 6f166e5fc..1ea736ca9 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_setb/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/memory_bank_use_setb/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_setb_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf index 41c819a8c..20914980b 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf @@ -16,10 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_bank_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout=2x2 +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_memory_bank/config/task.conf index f7e99fd89..b7368ad66 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_memory_bank/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_bank_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_memory_bank/config/task.conf index 66d4da4fb..29fcb228d 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/smart_fast_multi_region_memory_bank/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_bank_use_both_set_reset_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--fast_configuration [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 54a53bc988588bfe683b6c5db411cd465a7c1403 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 17:58:00 -0600 Subject: [PATCH 301/352] [Doc] Update documentation on the minor changes on bitstream file for memory bank protocol --- .../manual/file_formats/fabric_bitstream.rst | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index 46a7b852a..2def5d269 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -43,21 +43,25 @@ The information depends on the type of configuration procotol. .. option:: memory_bank - Multiple lines will be included, each of which is organized as
. - Note that due to the use of Bit-Line and Word-Line decoders, every two lines are paired. - The first line represents the Bit-Line address and configuration bit. - The second line represents the Word-Line address and configuration bit. + Multiple lines will be included, each of which is organized as . + The size of address line and data input bits are shown as a comment in the bitstream file, which eases the development of bitstream downloader. + For example + + .. code-block:: verilog + + // Bitstream width (LSB -> MSB): + + The first part represents the Bit-Line address. + The second part represents the Word-Line address. + The third part represents the configuration bit. For example .. code-block:: xml - - - - + + ... - - + .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. From 5ecd975ec7d4b0903ed05c28dabb959c4abe125b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 19:20:10 -0600 Subject: [PATCH 302/352] [Test] Bug fix --- .../full_testbench/multi_region_memory_bank/config/task.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf index 20914980b..004f3701a 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_memory_bank/config/task.conf @@ -19,7 +19,7 @@ fpga_flow=yosys_vpr openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_bank_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=2x2 +openfpga_vpr_device_layout=--device 2x2 openfpga_fast_configuration= [ARCHITECTURES] From 9808b61b36286c583d54836b4616482190967d23 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 20:06:39 -0600 Subject: [PATCH 303/352] [Tool] Bug fix on the unfit vector size of bit index register in Verilog testbench in some cases --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 3a237160c..6534d5cd6 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1993,11 +1993,11 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; fp << std::endl; - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; BasicPort bit_skip_reg(TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME, 1); print_verilog_comment(fp, "----- Registers used for fast configuration logic -----"); - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_REG, bit_skip_reg) << ";" << std::endl; print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); @@ -2176,7 +2176,7 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; fp << std::endl; - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; @@ -2312,7 +2312,7 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; fp << std::endl; - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << ") - 1:0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; From 366dcff75d15ffc90b360383741ff691c6da2b03 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 21:49:31 -0600 Subject: [PATCH 304/352] [Tool] Now 'write_full_testbench' supports flatten(vanilla) configuration protocol --- .../write_text_fabric_bitstream.cpp | 86 +++------------ .../fpga_verilog/verilog_top_testbench.cpp | 101 ++++++++++++++++++ 2 files changed, 114 insertions(+), 73 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index fdd27f649..5338d7b09 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -40,65 +40,6 @@ void write_fabric_bitstream_text_file_head(std::fstream& fp) { fp << "// Date: " << std::ctime(&end_time); } -/******************************************************************** - * Write a configuration bit into a plain text file - * The format depends on the type of configuration protocol - * - Vanilla (standalone): just put down pure 0|1 bitstream - * - Configuration chain: just put down pure 0|1 bitstream - * - Memory bank : - * - Frame-based configuration protocol :
- * - * Return: - * - 0 if succeed - * - 1 if critical errors occured - *******************************************************************/ -static -int write_fabric_config_bit_to_text_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const FabricBitId& fabric_bit, - const e_config_protocol_type& config_type) { - if (false == valid_file_stream(fp)) { - return 1; - } - - switch (config_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit)); - break; - case CONFIG_MEM_MEMORY_BANK: { - for (const char& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) { - fp << addr_bit; - } - write_space_to_file(fp, 1); - for (const char& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) { - fp << addr_bit; - } - write_space_to_file(fp, 1); - fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit)); - fp << "\n"; - break; - } - case CONFIG_MEM_FRAME_BASED: { - for (const char& addr_bit : fabric_bitstream.bit_address(fabric_bit)) { - fp << addr_bit; - } - write_space_to_file(fp, 1); - fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit)); - fp << "\n"; - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configuration protocol type!\n"); - return 1; - } - - return 0; -} - - /******************************************************************** * Write the flatten fabric bitstream to a plain text file * @@ -109,20 +50,20 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp, static int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp, const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const ConfigProtocol& config_protocol) { - int status = 0; - for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) { - status = write_fabric_config_bit_to_text_file(fp, bitstream_manager, - fabric_bitstream, - fabric_bit, - config_protocol.type()); - if (1 == status) { - return status; - } + const FabricBitstream& fabric_bitstream) { + if (false == valid_file_stream(fp)) { + return 1; } - return status; + /* Output bitstream size information */ + fp << "// Bitstream length: " << fabric_bitstream.num_bits() << std::endl; + + /* Output bitstream data */ + for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) { + fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit)); + } + + return 0; } /******************************************************************** @@ -356,8 +297,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage case CONFIG_MEM_STANDALONE: status = write_flatten_fabric_bitstream_to_text_file(fp, bitstream_manager, - fabric_bitstream, - config_protocol); + fabric_bitstream); break; case CONFIG_MEM_SCAN_CHAIN: status = write_config_chain_fabric_bitstream_to_text_file(fp, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 6534d5cd6..c138a3bd9 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1937,6 +1937,101 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp, } } +/******************************************************************** + * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol + * We will load the bitstream in the second clock cycle, right after the first reset cycle + *******************************************************************/ +static +void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Find Bit-Line and Word-Line port */ + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); + + /* Find Bit-Line and Word-Line port */ + ModulePortId bl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); + + ModulePortId wl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bitstream.num_bits()); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:0];"; + fp << std::endl; + + /* Initial value should be the first configuration bits + * In the rest of programming cycles, + * configuration bits are fed at the falling edge of programming clock. + * We do not care the value of scan_chain head during the first programming cycle + * It is reset anyway + */ + std::vector initial_bl_values(bl_port.get_width(), 0); + std::vector initial_wl_values(wl_port.get_width(), 0); + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + fp << "initial" << std::endl; + fp << "\tbegin" << std::endl; + print_verilog_comment(fp, "----- Configuration chain default input -----"); + fp << "\t\t"; + fp << generate_verilog_port_constant_values(bl_port, initial_bl_values); + fp << ";" << std::endl; + fp << "\t\t"; + fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); + fp << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ") begin" << std::endl; + + /* Enable all the WLs */ + std::vector enabled_wl_values(wl_port.get_width(), 1); + fp << "\t\t\t"; + fp << generate_verilog_port_constant_values(wl_port, enabled_wl_values); + fp << ";" << std::endl; + + fp << "\t\t\t"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_port); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0]"; + fp << ";" << std::endl; + + fp << "\t\tend" << std::endl; + + /* Disable all the WLs */ + fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; + + fp << "\t\t\t"; + fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); + fp << ";" << std::endl; + + /* Raise the flag of configuration done when bitstream loading is complete */ + fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t\t"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); + fp << " <= "; + std::vector config_done_enable_values(config_done_port.get_width(), 1); + fp << generate_verilog_constant_values(config_done_enable_values); + fp << ";" << std::endl; + + fp << "\tend" << std::endl; + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + /******************************************************************** * Print stimulus for a FPGA fabric with a configuration chain protocol * where configuration bits are programming in serial (one by one) @@ -2411,6 +2506,12 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, /* Branch on the type of configuration protocol */ switch (config_protocol_type) { case CONFIG_MEM_STANDALONE: + print_verilog_full_testbench_vanilla_bitstream(fp, + bitstream_file, + module_manager, + top_module, + fabric_bitstream); + break; case CONFIG_MEM_SCAN_CHAIN: print_verilog_full_testbench_configuration_chain_bitstream(fp, bitstream_file, From 462326aaa532ad908467c2b345f865991aac3885 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 21:50:00 -0600 Subject: [PATCH 305/352] [Test] Update full testbench test case for flatten configuration protocol using 'write_full_testbench' --- .../full_testbench/flatten_memory/config/task.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/flatten_memory/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/flatten_memory/config/task.conf index adaf26a25..f980071c0 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/flatten_memory/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/flatten_memory/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_standalone_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 4aef9d5c9669631b396741370e390659c51dd80c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 7 Jun 2021 21:54:01 -0600 Subject: [PATCH 306/352] [Tool] Remove redundant codes --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index c138a3bd9..7d2bc98ef 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -3063,11 +3063,6 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, netlist_annotation, explicit_port_mapping); - /* Print tasks used for loading bitstreams */ - print_verilog_top_testbench_load_bitstream_task(fp, - config_protocol.type(), - module_manager, top_module); - /* load bitstream to FPGA fabric in a configuration phase */ print_verilog_full_testbench_bitstream(fp, bitstream_file, From 5075c684185a10989d3f185f3d4debabb3affd20 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 8 Jun 2021 20:58:04 -0600 Subject: [PATCH 307/352] [Tool] Remove duplicated codes on fast configuration --- .../fpga_verilog/verilog_top_testbench.cpp | 124 ++---------------- 1 file changed, 8 insertions(+), 116 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 7d2bc98ef..40c4fdb55 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1461,102 +1461,6 @@ void print_verilog_top_testbench_vanilla_bitstream(std::fstream& fp, print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } -/******************************************************************** - * Decide if we should use reset or set signal to acheive fast configuration - * - If only one type signal is specified, we use that type - * For example, only reset signal is defined, we will use reset - * - If both are defined, pick the one that will bring bigger reduction - * i.e., larger number of configuration bits can be skipped - *******************************************************************/ -static -bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, - const bool& fast_configuration, - const std::vector& global_prog_reset_ports, - const std::vector& global_prog_set_ports, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - - /* Early exit conditions */ - if (!global_prog_reset_ports.empty() && global_prog_set_ports.empty()) { - return false; - } else if (!global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { - return true; - } else if (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { - /* If both types of ports are not defined, the fast configuration should be turned off */ - VTR_ASSERT(false == fast_configuration); - return false; - } - - VTR_ASSERT(!global_prog_set_ports.empty() && !global_prog_reset_ports.empty()); - bool bit_value_to_skip = false; - - VTR_LOG("Both reset and set ports are defined for programming controls, selecting the best-fit one...\n"); - - size_t num_ones_to_skip = 0; - size_t num_zeros_to_skip = 0; - - /* Branch on the type of configuration protocol */ - switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* We can only skip the ones/zeros at the beginning of the bitstream */ - /* Count how many logic '1' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - break; - } - VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); - num_ones_to_skip++; - } - /* Count how many logic '0' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - break; - } - VTR_ASSERT(false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); - num_zeros_to_skip++; - } - break; - } - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_FRAME_BASED: { - /* Count how many logic '1' and logic '0' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - num_zeros_to_skip++; - } else { - VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); - num_ones_to_skip++; - } - } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization type!\n"); - exit(1); - } - - VTR_LOG("Using reset will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_zeros_to_skip / (float) fabric_bitstream.num_bits(), - num_zeros_to_skip, fabric_bitstream.num_bits()); - - VTR_LOG("Using set will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_ones_to_skip / (float) fabric_bitstream.num_bits(), - num_ones_to_skip, fabric_bitstream.num_bits()); - - /* By default, we prefer to skip zeros (when the numbers are the same */ - if (num_ones_to_skip > num_zeros_to_skip) { - VTR_LOG("Will use set signal in fast configuration\n"); - bit_value_to_skip = true; - } else { - VTR_LOG("Will use reset signal in fast configuration\n"); - } - - return bit_value_to_skip; -} - /******************************************************************** * Print stimulus for a FPGA fabric with a configuration chain protocol * where configuration bits are programming in serial (one by one) @@ -2699,17 +2603,11 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); /* Identify if we can apply fast configuration */ - bool apply_fast_configuration = fast_configuration; - if ( (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) - && (true == fast_configuration)) { - VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is turned off\n"); - apply_fast_configuration = false; - } + bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - apply_fast_configuration, - global_prog_reset_ports, - global_prog_set_ports, - bitstream_manager, fabric_bitstream); + global_ports, + bitstream_manager, + fabric_bitstream); /* Start of testbench */ print_verilog_top_testbench_ports(fp, module_manager, top_module, @@ -2958,17 +2856,11 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); /* Identify if we can apply fast configuration */ - bool apply_fast_configuration = fast_configuration; - if ( (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) - && (true == fast_configuration)) { - VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is turned off\n"); - apply_fast_configuration = false; - } + bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - apply_fast_configuration, - global_prog_reset_ports, - global_prog_set_ports, - bitstream_manager, fabric_bitstream); + global_ports, + bitstream_manager, + fabric_bitstream); /* Start of testbench */ print_verilog_top_testbench_ports(fp, module_manager, top_module, From 8db19c7af9ff07f6a7dcb0ddd3e0a003ba917aba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 8 Jun 2021 21:28:16 -0600 Subject: [PATCH 308/352] [Tool] Add a new command 'write_preconfigured_fabric_wrapper' --- openfpga/src/base/openfpga_verilog.cpp | 42 +++++++- openfpga/src/base/openfpga_verilog.h | 5 +- .../src/base/openfpga_verilog_command.cpp | 101 +++++++++++++----- openfpga/src/fpga_verilog/verilog_api.cpp | 45 ++++++++ openfpga/src/fpga_verilog/verilog_api.h | 13 +++ 5 files changed, 180 insertions(+), 26 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 6cfb9879a..5ac0a49e0 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -122,7 +122,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, /******************************************************************** * A wrapper function to call the full testbench generator of FPGA-Verilog *******************************************************************/ -int write_full_testbench(OpenfpgaContext& openfpga_ctx, +int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); @@ -170,5 +170,45 @@ int write_full_testbench(OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the preconfigured wrapper generator of FPGA-Verilog + *******************************************************************/ +int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog + * Keep it independent from any other outside data structures + */ + VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); + options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_print_formal_verification_top_netlist(true); + + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + + return fpga_verilog_preconfigured_fabric_wrapper(openfpga_ctx.module_graph(), + openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), + g_vpr_ctx.placement(), + pin_constraints, + openfpga_ctx.io_location_map(), + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol, + options); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 20ce5d858..f755bf0bb 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -21,9 +21,12 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); -int write_full_testbench(OpenfpgaContext& openfpga_ctx, +int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 431eac47f..6a3c7c415 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -123,9 +123,9 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell& shell, @@ -133,46 +133,88 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell& dependent_cmds) { Command shell_cmd("write_full_testbench"); - /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + /* add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); - /* Add an option '--bitstream'*/ - CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "Specify the bitstream to be loaded in the testbench"); + /* add an option '--bitstream'*/ + CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "specify the bitstream to be loaded in the testbench"); shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING); - /* Add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric HDL netlist"); + /* add an option '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); - /* Add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); + /* add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "specify the file path to the pin constraints"); shell_cmd.set_option_short_name(pcf_opt, "pcf"); shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); - /* Add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); + /* add an option '--reference_benchmark_file_path'*/ + CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "specify the file path to the reference verilog netlist"); shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); - /* Add an option '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip certain data points"); + /* add an option '--fast_configuration' */ + shell_cmd.add_option("fast_configuration", false, "reduce the period of configuration by skip certain data points"); - /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + /* add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); - /* Add an option '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches"); + /* add an option '--include_signal_init' */ + shell_cmd.add_option("include_signal_init", false, "initialize all the signals in verilog testbenches"); - /* Add an option '--verbose' */ - shell_cmd.add_option("verbose", false, "Enable verbose output"); + /* add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "enable verbose output"); - /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an FPGA fabric"); + /* add command to the shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an fpga fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_full_testbench); - /* Add command dependency to the Shell */ + /* add command dependency to the shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + +/******************************************************************** + * - add a command to shell environment: write preconfigured fabric wrapper + * - add associated options + * - add command dependency + *******************************************************************/ +static +ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_preconfigured_fabric_wrapper"); + + /* add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* add an option '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); + + /* add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(pcf_opt, "pcf"); + shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); + + /* add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); + + /* add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "enable verbose output"); + + /* add command to the shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate a wrapper for a pre-configured fpga fabric"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_preconfigured_fabric_wrapper); + + /* add command dependency to the shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); return shell_cmd_id; @@ -214,6 +256,17 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { add_openfpga_write_full_testbench_command(shell, openfpga_verilog_cmd_class, full_testbench_dependent_cmds); + + /******************************** + * Command 'write_preconfigured_fabric_wrapper' + */ + /* The command 'write_preconfigured_fabric_wrapper' should NOT be executed before 'build_fabric' */ + std::vector preconfig_wrapper_dependent_cmds; + preconfig_wrapper_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_preconfigured_fabric_wrapper_command(shell, + openfpga_verilog_cmd_class, + preconfig_wrapper_dependent_cmds); + } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index fa0980eea..d7628570e 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -313,4 +313,49 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager, return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on full testbench generation + * This function will generate + * - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark + ********************************************************************/ +int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const PinConstraints& pin_constraints, + const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write a wrapper module for a preconfigured FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + /* Create directories */ + create_directory(src_dir_path); + + /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ + std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); + status = print_verilog_preconfig_top_module(module_manager, bitstream_manager, + config_protocol, + circuit_lib, fabric_global_port_info, + atom_ctx, place_ctx, + pin_constraints, + io_location_map, + netlist_annotation, + netlist_name, + formal_verification_top_netlist_file_path, + options.explicit_port_mapping()); + + return status; +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index f3f0b8321..f8665a0e8 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -72,6 +72,19 @@ int fpga_verilog_full_testbench(const ModuleManager& module_manager, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); +int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const PinConstraints& pin_constraints, + const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options); + + } /* end namespace openfpga */ #endif From 85679c0fe2292eeb1b2b14dfb7f74158295be8d8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 8 Jun 2021 21:32:26 -0600 Subject: [PATCH 309/352] [Tool] Bug fix in the top testbench switch due to fast configuration --- .../fpga_verilog/verilog_top_testbench.cpp | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 40c4fdb55..0eb5f39f0 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2604,10 +2604,13 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, /* Identify if we can apply fast configuration */ bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); - bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); + bool bit_value_to_skip = false; + if (true == apply_fast_configuration) { + bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), + global_ports, + bitstream_manager, + fabric_bitstream); + } /* Start of testbench */ print_verilog_top_testbench_ports(fp, module_manager, top_module, @@ -2857,10 +2860,13 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, /* Identify if we can apply fast configuration */ bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); - bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); + bool bit_value_to_skip = false; + if (true == apply_fast_configuration) { + bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), + global_ports, + bitstream_manager, + fabric_bitstream); + } /* Start of testbench */ print_verilog_top_testbench_ports(fp, module_manager, top_module, From d2275b971df31ad074cb4a0c7adc5bb239235eb8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 8 Jun 2021 21:53:51 -0600 Subject: [PATCH 310/352] [Tool] Add a new command 'write_preconfigured_testbench' --- openfpga/src/base/openfpga_verilog.cpp | 40 ++++++++++++++ openfpga/src/base/openfpga_verilog.h | 3 + .../src/base/openfpga_verilog_command.cpp | 55 +++++++++++++++++++ openfpga/src/fpga_verilog/verilog_api.cpp | 50 +++++++++++++++++ openfpga/src/fpga_verilog/verilog_api.h | 7 +++ 5 files changed, 155 insertions(+) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 5ac0a49e0..f62c9da71 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -180,6 +180,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); CommandOptionId opt_verbose = cmd.option("verbose"); /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog @@ -190,6 +191,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); options.set_print_formal_verification_top_netlist(true); /* If pin constraints are enabled by command options, read the file */ @@ -211,4 +213,42 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the preconfigured testbench generator of FPGA-Verilog + *******************************************************************/ +int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog + * Keep it independent from any other outside data structures + */ + VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_print_preconfig_top_testbench(true); + + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + + return fpga_verilog_preconfigured_testbench(openfpga_ctx.module_graph(), + g_vpr_ctx.atom(), + pin_constraints, + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), + openfpga_ctx.simulation_setting(), + options); +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index f755bf0bb..d7c0b5404 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -27,6 +27,9 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 6a3c7c415..f9d4acc65 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -206,6 +206,9 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga: /* add an option '--explicit_port_mapping' */ shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); + /* Add an option '--support_icarus_simulator' */ + shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator"); + /* add an option '--verbose' */ shell_cmd.add_option("verbose", false, "enable verbose output"); @@ -220,6 +223,48 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga: return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: write preconfigured testbench + * - Add associated options + * - Add command dependency + *******************************************************************/ +static +ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_preconfigured_testbench"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* Add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(pcf_opt, "pcf"); + shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); + + /* Add an option '--reference_benchmark_file_path'*/ + CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); + shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); + + /* Add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate testbenches for a preconfigured FPGA fabric"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_preconfigured_testbench); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + void add_openfpga_verilog_commands(openfpga::Shell& shell) { /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); @@ -267,6 +312,16 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds); + /******************************** + * Command 'write_preconfigured_testbench' + */ + /* The command 'write_preconfigured_testbench' should NOT be executed before 'build_fabric' */ + std::vector preconfig_testbench_dependent_cmds; + preconfig_testbench_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_preconfigured_testbench_command(shell, + openfpga_verilog_cmd_class, + preconfig_testbench_dependent_cmds); + } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index d7628570e..3c1624c1a 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -357,5 +357,55 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation + * This function will generate + * - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. + * This testbench is created for quick verification and formal verification purpose. + ********************************************************************/ +int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, + const AtomContext &atom_ctx, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const SimulationSetting &simulation_setting, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for a preconfigured FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + /* Create directories */ + create_directory(src_dir_path); + + /* Output preprocessing flags for HDL simulations */ + print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), + options); + + /* Generate top-level testbench using random vectors */ + std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + print_verilog_random_top_testbench(netlist_name, + random_top_testbench_file_path, + atom_ctx, + netlist_annotation, + module_manager, + fabric_global_port_info, + pin_constraints, + simulation_setting, + options.explicit_port_mapping()); + + /* Generate a Verilog file including all the netlists that have been generated */ + print_verilog_testbench_include_netlists(src_dir_path, + netlist_name, + options.fabric_netlist_file_path(), + options.reference_benchmark_file_path()); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index f8665a0e8..da6685f3b 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -84,6 +84,13 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage const ConfigProtocol &config_protocol, const VerilogTestbenchOption &options); +int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, + const AtomContext &atom_ctx, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const SimulationSetting &simulation_setting, + const VerilogTestbenchOption &options); } /* end namespace openfpga */ From 97396eda2be9439fddaad543a2350a329e806e9c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 8 Jun 2021 22:10:02 -0600 Subject: [PATCH 311/352] [Tool] Add a new command 'write_simulation_task_info' --- openfpga/src/base/openfpga_verilog.cpp | 27 ++++++++++++ openfpga/src/base/openfpga_verilog.h | 3 ++ .../src/base/openfpga_verilog_command.cpp | 43 +++++++++++++++++++ openfpga/src/fpga_verilog/verilog_api.cpp | 42 ++++++++++++++++++ openfpga/src/fpga_verilog/verilog_api.h | 9 ++++ 5 files changed, 124 insertions(+) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index f62c9da71..f3b6a7d9a 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -250,5 +250,32 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the simulation task information generator of FPGA-Verilog + *******************************************************************/ +int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog + * Keep it independent from any other outside data structures + */ + VerilogTestbenchOption options; + options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_output_dir)); + + return fpga_verilog_simulation_task_info(openfpga_ctx.module_graph(), + openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), + g_vpr_ctx.placement(), + openfpga_ctx.io_location_map(), + openfpga_ctx.simulation_setting(), + openfpga_ctx.arch().config_protocol, + options); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index d7c0b5404..7789335a8 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -30,6 +30,9 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index f9d4acc65..72115e987 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -265,6 +265,40 @@ ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shel return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: write simulation task info + * - Add associated options + * - Add command dependency + *******************************************************************/ +static +ShellCommandId add_openfpga_write_simulation_task_info_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_simulation_task_info"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the file path to output simulation-related information"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* Add an option '--reference_benchmark_file_path'*/ + CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); + shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate an interchangable simulation task configuration file"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_simulation_task_info); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + void add_openfpga_verilog_commands(openfpga::Shell& shell) { /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); @@ -322,6 +356,15 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { openfpga_verilog_cmd_class, preconfig_testbench_dependent_cmds); + /******************************** + * Command 'write_simulation_task_info' + */ + /* The command 'write_simulation_task_info' should NOT be executed before 'build_fabric' */ + std::vector sim_task_info_dependent_cmds; + sim_task_info_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_simulation_task_info_command(shell, + openfpga_verilog_cmd_class, + sim_task_info_dependent_cmds); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 3c1624c1a..d7ed62f64 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -407,5 +407,47 @@ int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation + * This function will generate + * - An interchangable file containing simulation task configuration + ********************************************************************/ +int fpga_verilog_simulation_task_info(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const IoLocationMap &io_location_map, + const SimulationSetting &simulation_setting, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write interchangeable simulation task configuration\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + /* Create directories */ + create_directory(src_dir_path); + + /* Generate exchangeable files which contains simulation settings */ + std::string simulation_ini_file_name = options.simulation_ini_path(); + VTR_ASSERT(true != options.simulation_ini_path().empty()); + print_verilog_simulation_info(simulation_ini_file_name, + netlist_name, + src_dir_path, + atom_ctx, place_ctx, io_location_map, + module_manager, + config_protocol.type(), + bitstream_manager.num_bits(), + simulation_setting.num_clock_cycles(), + simulation_setting.programming_clock_frequency(), + simulation_setting.default_operating_clock_frequency()); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index da6685f3b..0bfb397f8 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -92,6 +92,15 @@ int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, const SimulationSetting &simulation_setting, const VerilogTestbenchOption &options); +int fpga_verilog_simulation_task_info(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const IoLocationMap &io_location_map, + const SimulationSetting &simulation_setting, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options); + } /* end namespace openfpga */ #endif From be26c06673e399edd8d5a6494342d9cea2d9acee Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 10:41:22 -0600 Subject: [PATCH 312/352] [Script] Update an example script to use 'write_preconfigured_fabric_wrapper' and 'write_preconfigured_testbench' in place of 'write_verilog_testbench' --- .../behavioral_verilog_example_script.openfpga | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga index f8b7245b9..6e17e025f 100644 --- a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga @@ -55,17 +55,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --support_icarus_simulator --explicit_port_mapping - -# Write the SDC files for PnR backend -# - Turn on every options here -write_pnr_sdc --file ./SDC - -# Write SDC to disable timing for configure ports -write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc - -# Write the SDC to run timing analysis for a mapped FPGA fabric -write_analysis_sdc --file ./SDC_analysis +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Finish and exit OpenFPGA exit From 89fb67263179c1477fb7f6c18df9f1aafa4cef2a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 10:49:00 -0600 Subject: [PATCH 313/352] [Tool] Fine-tune the options of 'write_simulation_task_info' to be straightforward to use --- openfpga/src/base/openfpga_verilog.cpp | 6 ++++-- openfpga/src/base/openfpga_verilog_command.cpp | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index f3b6a7d9a..50cd9ba87 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -256,7 +256,8 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { - CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_file = cmd.option("file"); + CommandOptionId opt_hdl_dir = cmd.option("hdl_dir"); CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -264,9 +265,10 @@ int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, * Keep it independent from any other outside data structures */ VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_hdl_dir)); options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); - options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_output_dir)); + options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_file)); return fpga_verilog_simulation_task_info(openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 72115e987..471e8784b 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -281,6 +281,10 @@ ShellCommandId add_openfpga_write_simulation_task_info_command(openfpga::Shell Date: Wed, 9 Jun 2021 11:14:45 -0600 Subject: [PATCH 314/352] [Tool] Add '--fabric_netlist' option to 'write_preconfigured_testbench' command --- openfpga/src/base/openfpga_verilog.cpp | 2 ++ openfpga/src/base/openfpga_verilog_command.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 50cd9ba87..a14031c03 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -221,6 +221,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -230,6 +231,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, */ VerilogTestbenchOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 471e8784b..f022ac779 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -239,6 +239,10 @@ ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shel shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + /* add an option '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); + /* Add an option '--pin_constraints_file in short '-pcf' */ CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); shell_cmd.set_option_short_name(pcf_opt, "pcf"); From 9adf94bfd37efbb1f5944e19b3702ef031ee0b21 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 11:18:52 -0600 Subject: [PATCH 315/352] [Script] Update all the openshell scripts to deprecate 'write_verilog_testbench' --- .../bitstream_setting_example_script.openfpga | 3 ++- .../configuration_chain_example_script.openfpga | 3 ++- .../custom_fabric_netlist_example_script.openfpga | 2 +- .../duplicated_grid_pin_example_script.openfpga | 3 ++- openfpga_flow/openfpga_shell_scripts/example_script.openfpga | 4 +++- .../example_without_ace_script.openfpga | 4 +++- .../fast_configuration_example_script.openfpga | 2 +- .../fix_device_example_script.openfpga | 4 +++- ...obal_tile_clock_bitstream_setting_example_script.openfpga | 4 +++- .../fix_device_global_tile_clock_example_script.openfpga | 4 +++- .../fix_device_route_chan_width_example_script.openfpga | 4 +++- .../fix_heterogeneous_device_example_script.openfpga | 5 +++-- .../flatten_routing_example_script.openfpga | 4 +++- .../full_testbench_example_script.openfpga | 2 +- .../generate_secure_fabric_example_script.openfpga | 4 +++- .../generate_secure_fabric_from_key_example_script.openfpga | 4 +++- .../generate_testbench_example_script.openfpga | 4 ++++ .../global_tile_clock_example_script.openfpga | 4 +++- .../global_tile_multiclock_example_script.openfpga | 4 +++- .../implicit_verilog_example_script.openfpga | 4 +++- .../openfpga_shell_scripts/iverilog_example_script.openfpga | 4 +++- .../load_external_arch_bitstream_example_script.openfpga | 2 +- .../openfpga_shell_scripts/mcnc_example_script.openfpga | 3 ++- .../skywater_tapeout_example_script.openfpga | 4 +++- .../verilog_default_net_type_example_script.openfpga | 4 +++- 25 files changed, 64 insertions(+), 25 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga index a5cbbaf16..304aa0830 100644 --- a/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga @@ -58,7 +58,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga index 67c1419bd..d6a6eaa24 100644 --- a/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga @@ -55,7 +55,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga index 3bc847bdf..00cd426b9 100644 --- a/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./FABRIC_NETLIST --explicit_port_mapping --include_t # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --fabric_netlist_file_path ${OPENFPGA_FABRIC_NETLIST_FILE} --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --fabric_netlist_file_path ${OPENFPGA_FABRIC_NETLIST_FILE} --explicit_port_mapping --include_signal_init # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga index 227e1fdda..3d9ea31d5 100644 --- a/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga @@ -55,7 +55,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga index 18b7c97f2..573e0d683 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index 3c1be9114..5ba6156f7 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga index 0699d4ea6..f4f786e73 100644 --- a/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping --fast_configuration +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fast_configuration # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga index ef37d9242..65c278217 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga index dabb0c6c6..fcc402c14 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga @@ -58,7 +58,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga index b5fd710b6..7bc46ced1 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga @@ -57,7 +57,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga index 054f74c0e..137138902 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga index 1d6cca82f..a4a1e68c5 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga @@ -55,8 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping - +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here write_pnr_sdc --file ./SDC diff --git a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga index dccde3d8c..6e974623d 100644 --- a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga index 18b7c97f2..f2ddca635 100644 --- a/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga index b7a856dfd..2c3653bae 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga @@ -58,7 +58,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga index 8d8d07d32..30e4eb5a9 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga @@ -58,7 +58,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga index 197c350bd..4db82b16c 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga @@ -53,6 +53,10 @@ write_fabric_bitstream --file fabric_bitstream --format xml # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} + # Write the SDC to run timing analysis for a mapped FPGA fabric write_analysis_sdc --file ./SDC_analysis diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga index b418685ab..2809dafb1 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga @@ -57,7 +57,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga index 93af8bdb1..0b1179e3e 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga @@ -61,7 +61,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} #--explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga index 6c793bc88..a335baf75 100644 --- a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --include_timing --print_user_defined_template # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga index e161d8e2f..769163de8 100644 --- a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga @@ -52,7 +52,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga index 976087ded..2830f5fc4 100644 --- a/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga @@ -58,7 +58,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga index 6c753df2f..1f41dfc84 100644 --- a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga @@ -56,7 +56,8 @@ write_fabric_verilog --file ./SRC \ # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ./${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./simulation_deck_info.ini +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga index e9195e9e7..f21b4d1ce 100644 --- a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga index 6cb86439c..92d6bfbcc 100644 --- a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga @@ -55,7 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping # Write the SDC files for PnR backend # - Turn on every options here From f9404dc97d5ec7ca11be6a8f2c6f2c7af2e0f713 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 11:55:25 -0600 Subject: [PATCH 316/352] [Script] Patch openfpga shell script due to missing a mandatory option in 'write_full_testbench' --- .../custom_fabric_netlist_example_script.openfpga | 4 ++-- .../openfpga_shell_scripts/example_script.openfpga | 4 ++-- .../example_without_ace_script.openfpga | 4 ++-- .../fast_configuration_example_script.openfpga | 4 ++-- .../fix_device_example_script.openfpga | 4 ++-- ...bal_tile_clock_bitstream_setting_example_script.openfpga | 4 ++-- .../fix_device_global_tile_clock_example_script.openfpga | 4 ++-- .../fix_device_route_chan_width_example_script.openfpga | 4 ++-- .../fix_heterogeneous_device_example_script.openfpga | 4 ++-- .../flatten_routing_example_script.openfpga | 4 ++-- .../full_testbench_example_script.openfpga | 4 ++-- .../generate_secure_fabric_example_script.openfpga | 4 ++-- .../generate_secure_fabric_from_key_example_script.openfpga | 4 ++-- .../generate_testbench_example_script.openfpga | 6 ++---- .../global_tile_clock_example_script.openfpga | 4 ++-- .../global_tile_multiclock_example_script.openfpga | 4 ++-- .../implicit_verilog_example_script.openfpga | 4 ++-- .../openfpga_shell_scripts/iverilog_example_script.openfpga | 5 ++++- .../load_external_arch_bitstream_example_script.openfpga | 4 ++-- .../skywater_tapeout_example_script.openfpga | 4 ++-- .../verilog_default_net_type_example_script.openfpga | 4 ++-- 21 files changed, 44 insertions(+), 43 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga index 00cd426b9..1e1b46d23 100644 --- a/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/custom_fabric_netlist_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./FABRIC_NETLIST --explicit_port_mapping --include_t # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --fabric_netlist_file_path ${OPENFPGA_FABRIC_NETLIST_FILE} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --fabric_netlist_file_path ${OPENFPGA_FABRIC_NETLIST_FILE} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga index 573e0d683..450e1898c 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index 5ba6156f7..f127f69ac 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} diff --git a/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga index f4f786e73..77af24936 100644 --- a/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fast_configuration +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fast_configuration --bitstream fabric_bitstream.bit # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga index 65c278217..acaf5bdee 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga index fcc402c14..b93e9672e 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga @@ -46,7 +46,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -58,7 +58,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga index 7bc46ced1..58ad5efec 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga @@ -45,7 +45,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga index 137138902..af1af2f1f 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitsream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga index a4a1e68c5..3b173d694 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} # Write the SDC files for PnR backend diff --git a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga index 6e974623d..ce5e43570 100644 --- a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga index f2ddca635..84c107af9 100644 --- a/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/full_testbench_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga index 2c3653bae..be6014b73 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga @@ -46,7 +46,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -58,7 +58,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga index 30e4eb5a9..e975263d5 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga @@ -46,7 +46,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -58,7 +58,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga index 4db82b16c..2c90659b7 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog testbench for FPGA fabric # - We suggest the use of same output directory as fabric Verilog netlists @@ -51,9 +51,7 @@ write_fabric_bitstream --file fabric_bitstream --format xml # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} - -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga index 2809dafb1..647c8b627 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga @@ -45,7 +45,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga index 0b1179e3e..fad8dd893 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga @@ -49,7 +49,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -61,7 +61,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} diff --git a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga index a335baf75..d08a051a2 100644 --- a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --include_timing --print_user_defined_template # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} diff --git a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga index 769163de8..1a1bf0eb1 100644 --- a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga @@ -42,6 +42,9 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream # Build fabric-dependent bitstream build_fabric_bitstream --verbose +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose @@ -52,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} diff --git a/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga index 2830f5fc4..1a94138a4 100644 --- a/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/load_external_arch_bitstream_example_script.openfpga @@ -46,7 +46,7 @@ build_architecture_bitstream --verbose \ build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -58,7 +58,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga index f21b4d1ce..93700ded6 100644 --- a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping diff --git a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga index 92d6bfbcc..cff7cd35c 100644 --- a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga @@ -43,7 +43,7 @@ build_architecture_bitstream --verbose --write_file fabric_independent_bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping From 2299ce3157a8e01a3903538a4b47f85016004e43 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 13:49:25 -0600 Subject: [PATCH 317/352] [Tool] Preconfigured testbench writer now supports icarus simulator --- openfpga/src/base/openfpga_verilog.cpp | 2 ++ openfpga/src/base/openfpga_verilog_command.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index a14031c03..cc737554b 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -223,6 +223,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -233,6 +234,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_preconfig_top_testbench(true); diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index f022ac779..79388c4b9 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -252,6 +252,9 @@ ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shel CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); + /* Add an option '--support_icarus_simulator' */ + shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator"); + /* Add an option '--explicit_port_mapping' */ shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); From 4e3f589810f75486996b77d8fad9a35676ff2c99 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 13:53:28 -0600 Subject: [PATCH 318/352] [Script] Patch openfpga shell script to use the new option '--support_icarus_simulator' for 'write_preconfigured_testbench' --- .../behavioral_verilog_example_script.openfpga | 2 +- .../bitstream_setting_example_script.openfpga | 2 +- .../configuration_chain_example_script.openfpga | 2 +- .../duplicated_grid_pin_example_script.openfpga | 2 +- openfpga_flow/openfpga_shell_scripts/example_script.openfpga | 2 +- .../openfpga_shell_scripts/example_without_ace_script.openfpga | 2 +- .../openfpga_shell_scripts/fix_device_example_script.openfpga | 2 +- ...global_tile_clock_bitstream_setting_example_script.openfpga | 2 +- .../fix_device_global_tile_clock_example_script.openfpga | 2 +- .../fix_device_route_chan_width_example_script.openfpga | 2 +- .../fix_heterogeneous_device_example_script.openfpga | 3 ++- .../flatten_routing_example_script.openfpga | 2 +- .../generate_secure_fabric_example_script.openfpga | 2 +- .../generate_secure_fabric_from_key_example_script.openfpga | 2 +- .../generate_testbench_example_script.openfpga | 2 +- .../global_tile_clock_example_script.openfpga | 2 +- .../global_tile_multiclock_example_script.openfpga | 2 +- .../implicit_verilog_example_script.openfpga | 2 +- .../openfpga_shell_scripts/iverilog_example_script.openfpga | 2 +- .../openfpga_shell_scripts/mcnc_example_script.openfpga | 2 +- .../skywater_tapeout_example_script.openfpga | 2 +- .../verilog_default_net_type_example_script.openfpga | 2 +- 22 files changed, 23 insertions(+), 22 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga index 6e17e025f..d27d4eff6 100644 --- a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga @@ -56,7 +56,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Finish and exit OpenFPGA exit diff --git a/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga index 304aa0830..2d4820510 100644 --- a/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga @@ -59,7 +59,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga index d6a6eaa24..34e56c3b9 100644 --- a/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/configuration_chain_example_script.openfpga @@ -56,7 +56,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga index 3d9ea31d5..cf9cbd8b5 100644 --- a/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/duplicated_grid_pin_example_script.openfpga @@ -56,7 +56,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga index 450e1898c..71e6fd224 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index f127f69ac..b5a9fe352 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga index acaf5bdee..94a9a41c5 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga index b93e9672e..ea4f9912e 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_bitstream_setting_example_script.openfpga @@ -60,7 +60,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga index 58ad5efec..c40e79c79 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_global_tile_clock_example_script.openfpga @@ -59,7 +59,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga index af1af2f1f..d31ffe36c 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitsream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga index 3b173d694..79430e976 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga @@ -57,7 +57,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator + # Write the SDC files for PnR backend # - Turn on every options here write_pnr_sdc --file ./SDC diff --git a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga index ce5e43570..4511ba34d 100644 --- a/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/flatten_routing_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga index be6014b73..571ceee8f 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga @@ -60,7 +60,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga index e975263d5..857b20981 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga @@ -60,7 +60,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga index 2c90659b7..19487e48b 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_testbench_example_script.openfpga @@ -53,7 +53,7 @@ write_fabric_bitstream --file fabric_bitstream.bit --format plain_text # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} --support_icarus_simulator # Write the SDC to run timing analysis for a mapped FPGA fabric write_analysis_sdc --file ./SDC_analysis diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga index 647c8b627..bc56dc8ee 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga @@ -59,7 +59,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga index fad8dd893..5fe8cd4b5 100644 --- a/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga @@ -63,7 +63,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga index d08a051a2..c0752db76 100644 --- a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --include_timing --print_user_defined_template # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga index 1a1bf0eb1..d44e57a24 100644 --- a/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/iverilog_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga index 1f41dfc84..56b5c9caf 100644 --- a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC \ # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga index 93700ded6..7cfe311f3 100644 --- a/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/skywater_tapeout_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga index cff7cd35c..77f01d371 100644 --- a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga @@ -57,7 +57,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here From c62666e7c3da09678e61ce6e4453eb7f123eb0ce Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 14:24:34 -0600 Subject: [PATCH 319/352] [Test] Use proper template for some failing tests --- .../tasks/basic_tests/fixed_device_support/config/task.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/fixed_device_support/config/task.conf b/openfpga_flow/tasks/basic_tests/fixed_device_support/config/task.conf index 3fea70cef..d80ebe9c4 100644 --- a/openfpga_flow/tasks/basic_tests/fixed_device_support/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/fixed_device_support/config/task.conf @@ -16,11 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_frame_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=2x2 -openfpga_vpr_route_chan_width=40 +openfpga_vpr_device_layout=--device 2x2 --route_chan_width 40 +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 52c0ed571bad2c5d545ed6e15a907d52ee32fee9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 14:27:02 -0600 Subject: [PATCH 320/352] [Test] Patch test case to use proper template --- .../synthesizable_verilog/config/task.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/tasks/fpga_verilog/verilog_netlist_formats/synthesizable_verilog/config/task.conf b/openfpga_flow/tasks/fpga_verilog/verilog_netlist_formats/synthesizable_verilog/config/task.conf index 22fe003b9..0e60465b0 100644 --- a/openfpga_flow/tasks/fpga_verilog/verilog_netlist_formats/synthesizable_verilog/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/verilog_netlist_formats/synthesizable_verilog/config/task.conf @@ -16,12 +16,12 @@ timeout_each_job = 20*60 fpga_flow=vpr_blif [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga #openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_stdcell_mux_40nm_openfpga_synthesizable.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=auto -openfpga_vpr_route_chan_width=20 +openfpga_vpr_device_layout=--device auto --route_chan_width 20 +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml From d545069aacb2fba6e478d1e9b26f5fcaa43fcc93 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 14:50:37 -0600 Subject: [PATCH 321/352] [Script] Bug fix --- .../example_without_ace_script.openfpga | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index b5a9fe352..61c5ea8af 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -55,9 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit -write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --support_icarus_simulator +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bitstream fabric_bitstream.bit +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --support_icarus_simulator # Write the SDC files for PnR backend # - Turn on every options here From eed30605d7667a4f19d228f7ac83eb3f4b61bbf0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 15:20:55 -0600 Subject: [PATCH 322/352] [Test] patch test case --- .../power_gated_design/power_gated_inverter/config/task.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/fpga_verilog/power_gated_design/power_gated_inverter/config/task.conf b/openfpga_flow/tasks/fpga_verilog/power_gated_design/power_gated_inverter/config/task.conf index 1e919ff29..9bc003ff1 100644 --- a/openfpga_flow/tasks/fpga_verilog/power_gated_design/power_gated_inverter/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/power_gated_design/power_gated_inverter/config/task.conf @@ -16,9 +16,11 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fast_configuration_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From b719419931e8171dd08d216724dfc805ec067e40 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 16:59:02 -0600 Subject: [PATCH 323/352] [Doc] Update documentation on the FPGA-Verilog commands in openfpga shell; Deprecated the 'write_verilog_testbench' command --- .../fpga_verilog_commands.rst | 140 +++++++++++------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index 8b559c698..5c57d104e 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -6,7 +6,7 @@ FPGA-Verilog write_fabric_verilog ~~~~~~~~~~~~~~~~~~~~ - Write the Verilog netlist for FPGA fabric based on module graph + Write the Verilog netlist for FPGA fabric based on module graph. See details in :ref:`fabric_netlists`. .. option:: --file or -f @@ -40,58 +40,10 @@ write_fabric_verilog Show verbose log -write_verilog_testbench -~~~~~~~~~~~~~~~~~~~~~~~ - - Write the Verilog testbench for FPGA fabric - - .. option:: --file or -f - - The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` - - .. option:: --fabric_netlist_file_path - - Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v`` - - .. option:: --reference_benchmark_file_path - - Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v`` - - .. option:: --pin_constraints_file or -pcf - - Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` - Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. - - .. option:: --fast_configuration - - Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal. - - .. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration. - - .. option:: --print_top_testbench - - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA - - .. option:: --print_formal_verification_top_netlist - - Generate a top-level module which can be used in formal verification - - .. option:: --print_preconfig_top_testbench - - Enable pre-configured top-level testbench which is a fast verification skipping programming phase - - .. option:: --print_simulation_ini - - Output an exchangeable simulation ini file, which is needed only when you need to interface different HDL simulators using openfpga flow-run scripts. For example, ``--print_simulation_ini /temp/testbench/sim.ini`` - - .. option:: --explicit_port_mapping - - Use explicit port mapping when writing the Verilog netlists - write_full_testbench ~~~~~~~~~~~~~~~~~~~~~~~ - Write the full testbench for FPGA fabric in Verilog format + Write the full testbench for FPGA fabric in Verilog format. See details in :ref:`fpga_verilog_testbench`. .. option:: --file or -f @@ -128,4 +80,92 @@ write_full_testbench Output signal initialization to Verilog testbench to smooth convergence in HDL simulation + .. option:: --verbose + Show verbose log + +write_preconfigured_fabric_wrapper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Write the Verilog wrapper for a preconfigured FPGA fabric. See details in :ref:`fpga_verilog_testbench`. + + .. option:: --file or -f + + The output directory for the netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` + + .. option:: --fabric_netlist_file_path + + Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v`` + + .. option:: --pin_constraints_file or -pcf + + Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` + Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. + + .. option:: --explicit_port_mapping + + Use explicit port mapping when writing the Verilog netlists + + .. option:: --support_icarus_simulator + + Output Verilog netlists with syntax that iVerilog simulator can accept + + .. option:: --verbose + + Show verbose log + +write_preconfigured_testbench +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Write the Verilog testbench for a preconfigured FPGA fabric. See details in :ref:`fpga_verilog_testbench`. + + .. option:: --file or -f + + The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` + + .. option:: --fabric_netlist_file_path + + Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v`` + + .. option:: --reference_benchmark_file_path + + Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v`` + + .. option:: --pin_constraints_file or -pcf + + Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` + Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. + + .. option:: --explicit_port_mapping + + Use explicit port mapping when writing the Verilog netlists + + .. option:: --support_icarus_simulator + + Output Verilog netlists with syntax that iVerilog simulator can accept + + .. option:: --verbose + + Show verbose log + +write_simulation_task_info +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Write an interchangeable file in ``.ini`` format to interface HDL simulators, such as iVerilog and Modelsim. + + .. option:: --file or -f + + Specify the file path to output simulation-related information. For example, ``--file simulation.ini`` + + .. option:: --hdl_dir + + Specify the directory path where HDL netlists are created. For example, ``--hdl_dir ./SRC`` + + .. option:: --reference_benchmark_file_path + + Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v`` + + .. option:: --verbose + + Show verbose log + From 7ade48343cec8fa51c0f2b40f912c9043c950485 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 17:06:01 -0600 Subject: [PATCH 324/352] [Tool] Deprecate command 'write_verilog_testbench' --- openfpga/src/base/openfpga_verilog.cpp | 58 -- openfpga/src/base/openfpga_verilog.h | 3 - .../src/base/openfpga_verilog_command.cpp | 78 -- openfpga/src/fpga_verilog/verilog_api.cpp | 113 --- openfpga/src/fpga_verilog/verilog_api.h | 14 - .../fpga_verilog/verilog_top_testbench.cpp | 951 ------------------ .../src/fpga_verilog/verilog_top_testbench.h | 16 - 7 files changed, 1233 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index cc737554b..e279f1200 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -61,64 +61,6 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, return CMD_EXEC_SUCCESS; } -/******************************************************************** - * A wrapper function to call the Verilog testbench generator of FPGA-Verilog - *******************************************************************/ -int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - - CommandOptionId opt_output_dir = cmd.option("file"); - CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); - CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); - CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); - CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench"); - CommandOptionId opt_fast_configuration = cmd.option("fast_configuration"); - CommandOptionId opt_print_formal_verification_top_netlist = cmd.option("print_formal_verification_top_netlist"); - CommandOptionId opt_print_preconfig_top_testbench = cmd.option("print_preconfig_top_testbench"); - CommandOptionId opt_print_simulation_ini = cmd.option("print_simulation_ini"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); - CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); - CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); - CommandOptionId opt_verbose = cmd.option("verbose"); - - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures - */ - VerilogTestbenchOption options; - options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); - options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); - options.set_print_formal_verification_top_netlist(cmd_context.option_enable(cmd, opt_print_formal_verification_top_netlist)); - options.set_print_preconfig_top_testbench(cmd_context.option_enable(cmd, opt_print_preconfig_top_testbench)); - options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration)); - options.set_print_top_testbench(cmd_context.option_enable(cmd, opt_print_top_testbench)); - options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_print_simulation_ini)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); - options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); - options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); - options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); - - /* If pin constraints are enabled by command options, read the file */ - PinConstraints pin_constraints; - if (true == cmd_context.option_enable(cmd, opt_pcf)) { - pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); - } - - return fpga_verilog_testbench(openfpga_ctx.module_graph(), - openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - pin_constraints, - openfpga_ctx.io_location_map(), - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.simulation_setting(), - openfpga_ctx.arch().config_protocol, - options); -} - /******************************************************************** * A wrapper function to call the full testbench generator of FPGA-Verilog *******************************************************************/ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 7789335a8..3bbd7fab3 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -18,9 +18,6 @@ namespace openfpga { int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); -int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); - int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 79388c4b9..174b8a4d7 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -54,74 +54,6 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - Command shell_cmd("write_verilog_testbench"); - - /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for Verilog netlists"); - shell_cmd.set_option_short_name(output_opt, "f"); - shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); - - /* Add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist"); - shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); - - /* Add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); - shell_cmd.set_option_short_name(pcf_opt, "pcf"); - shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); - - /* Add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); - shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); - - /* Add an option '--print_top_testbench' */ - shell_cmd.add_option("print_top_testbench", false, "Generate a full testbench for top-level fabric module with autocheck capability"); - - /* Add an option '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip zero data points"); - - /* Add an option '--print_formal_verification_top_netlist' */ - shell_cmd.add_option("print_formal_verification_top_netlist", false, "Generate a top-level module which can be used in formal verification"); - - /* Add an option '--print_preconfig_top_testbench' */ - shell_cmd.add_option("print_preconfig_top_testbench", false, "Generate a pre-configured testbench for top-level fabric module with autocheck capability"); - - /* Add an option '--print_simulation_ini' */ - CommandOptionId sim_ini_opt = shell_cmd.add_option("print_simulation_ini", false, "Generate a .ini file as an exchangeable file to enable HDL simulations"); - shell_cmd.set_option_require_value(sim_ini_opt, openfpga::OPT_STRING); - - /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); - - /* Add an option '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches"); - - /* Add an option '--support_icarus_simulator' */ - shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator"); - - /* Add an option '--verbose' */ - shell_cmd.add_option("verbose", false, "Enable verbose output"); - - /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate Verilog testbenches for full FPGA fabric"); - shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, write_verilog_testbench); - - /* Add command dependency to the Shell */ - shell.set_command_dependency(shell_cmd_id, dependent_cmds); - - return shell_cmd_id; -} - /******************************************************************** * - add a command to shell environment: write full testbench * - add associated options @@ -327,16 +259,6 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { openfpga_verilog_cmd_class, fabric_verilog_dependent_cmds); - /******************************** - * Command 'write_verilog_testbench' - */ - /* The command 'write_verilog_testbench' should NOT be executed before 'build_fabric' */ - std::vector verilog_testbench_dependent_cmds; - verilog_testbench_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_verilog_testbench_command(shell, - openfpga_verilog_cmd_class, - verilog_testbench_dependent_cmds); - /******************************** * Command 'write_full_testbench' */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index d7ed62f64..f114f6d36 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -139,119 +139,6 @@ void fpga_fabric_verilog(ModuleManager &module_manager, module_manager.num_modules()); } -/******************************************************************** - * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation - * This function will generate - * - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark - * - Testbench, where a FPGA module is configured with a bitstream and then driven by input vectors - * - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. - * This testbench is created for quick verification and formal verification purpose. - * - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated - ********************************************************************/ -int fpga_verilog_testbench(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const FabricBitstream &fabric_bitstream, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap &io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const CircuitLibrary &circuit_lib, - const SimulationSetting &simulation_setting, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n"); - - std::string src_dir_path = format_dir_path(options.output_directory()); - - std::string netlist_name = atom_ctx.nlist.netlist_name(); - - int status = CMD_EXEC_SUCCESS; - - /* Create directories */ - create_directory(src_dir_path); - - /* Output preprocessing flags for HDL simulations */ - print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), - options); - - /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ - if (true == options.print_formal_verification_top_netlist()) { - std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); - status = print_verilog_preconfig_top_module(module_manager, bitstream_manager, - config_protocol, - circuit_lib, fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - io_location_map, - netlist_annotation, - netlist_name, - formal_verification_top_netlist_file_path, - options.explicit_port_mapping()); - if (status == CMD_EXEC_FATAL_ERROR) { - return status; - } - } - - if (true == options.print_preconfig_top_testbench()) { - /* Generate top-level testbench using random vectors */ - std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_random_top_testbench(netlist_name, - random_top_testbench_file_path, - atom_ctx, - netlist_annotation, - module_manager, - fabric_global_port_info, - pin_constraints, - simulation_setting, - options.explicit_port_mapping()); - } - - /* Generate full testbench for verification, including configuration phase and operating phase */ - if (true == options.print_top_testbench()) { - std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_top_testbench(module_manager, - bitstream_manager, fabric_bitstream, - circuit_lib, - config_protocol, - fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - io_location_map, - netlist_annotation, - netlist_name, - top_testbench_file_path, - simulation_setting, - options); - } - - /* Generate exchangeable files which contains simulation settings */ - if (true == options.print_simulation_ini()) { - std::string simulation_ini_file_name = options.simulation_ini_path(); - VTR_ASSERT(true != options.simulation_ini_path().empty()); - print_verilog_simulation_info(simulation_ini_file_name, - netlist_name, - src_dir_path, - atom_ctx, place_ctx, io_location_map, - module_manager, - config_protocol.type(), - bitstream_manager.num_bits(), - simulation_setting.num_clock_cycles(), - simulation_setting.programming_clock_frequency(), - simulation_setting.default_operating_clock_frequency()); - } - - /* Generate a Verilog file including all the netlists that have been generated */ - print_verilog_testbench_include_netlists(src_dir_path, - netlist_name, - options.fabric_netlist_file_path(), - options.reference_benchmark_file_path()); - - return status; -} - /******************************************************************** * A top-level function of FPGA-Verilog which focuses on full testbench generation * This function will generate diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 0bfb397f8..934dc08f7 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -43,20 +43,6 @@ void fpga_fabric_verilog(ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, const FabricVerilogOption& options); -int fpga_verilog_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation& netlist_annotation, - const CircuitLibrary& circuit_lib, - const SimulationSetting& simulation_parameters, - const ConfigProtocol& config_protocol, - const VerilogTestbenchOption& options); - int fpga_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 0eb5f39f0..779b6ceaa 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -945,229 +945,6 @@ void print_verilog_top_testbench_benchmark_instance(std::fstream& fp, fp << std::endl; } -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for configuration-chain manipulation: - * During each programming cycle, we feed the input of scan chain with a memory bit - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort cc_head_port = module_manager.module_port(top_module, cc_head_port_id); - BasicPort cc_head_value(generate_configuration_chain_head_name() + std::string("_val"), cc_head_port.get_width()); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the scan-chain input at each falling edge of programming clock - * It aims at avoid racing the programming clock (scan-chain data changes at the rising edge). - */ - print_verilog_comment(fp, std::string("----- Task: input values during a programming clock cycle -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_value); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for memory bank manipulation: - * During each programming cycle, we feed - * - an address to the BL address port of top module - * - an address to the WL address port of top module - * - a data input to the din port of top module - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_memory_bank(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); - BasicPort bl_addr_value = bl_addr_port; - bl_addr_value.set_name(std::string(MEMORY_BL_PORT_NAME) + std::string("_val")); - - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); - BasicPort wl_addr_value = wl_addr_port; - wl_addr_value.set_name(std::string(MEMORY_WL_PORT_NAME) + std::string("_val")); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - BasicPort din_value = din_port; - din_value.set_name(std::string(DECODER_DATA_IN_PORT_NAME) + std::string("_val")); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the address and data input at each falling edge of programming clock - * As the enable signal is wired to the programming clock, we should synchronize - * address and data with the enable signal - */ - print_verilog_comment(fp, std::string("----- Task: assign BL and WL address, and data values at rising edge of enable signal -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, bl_addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, wl_addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, din_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - - -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for frame-based memory manipulation: - * During each programming cycle, we feed - * - an address to the address port of top module - * - a data input to the din port of top module - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_frame_decoder(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); - BasicPort addr_value = addr_port; - addr_value.set_name(std::string(DECODER_ADDRESS_PORT_NAME) + std::string("_val")); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - BasicPort din_value = din_port; - din_value.set_name(std::string(DECODER_DATA_IN_PORT_NAME) + std::string("_val")); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the address and data input at each falling edge of programming clock - * As the enable signal is wired to the programming clock, we should synchronize - * address and data with the enable signal - */ - print_verilog_comment(fp, std::string("----- Task: assign address and data values at rising edge of enable signal -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, din_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - -/******************************************************************** - * Print tasks, which is very useful in generating stimuli for each clock cycle - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp, - const e_config_protocol_type& sram_orgz_type, - const ModuleManager& module_manager, - const ModuleId& top_module) { - switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* No need to have a specific task. Loading is done in 1 clock cycle */ - break; - case CONFIG_MEM_SCAN_CHAIN: - print_verilog_top_testbench_load_bitstream_task_configuration_chain(fp, - module_manager, - top_module); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_top_testbench_load_bitstream_task_memory_bank(fp, - module_manager, - top_module); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_top_testbench_load_bitstream_task_frame_decoder(fp, - module_manager, - top_module); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); - } -} - /******************************************************************** * Print generatic input stimuli for the top testbench * include: @@ -1370,477 +1147,6 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f } } -/******************************************************************** - * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol - * We will load the bitstream in the second clock cycle, right after the first reset cycle - *******************************************************************/ -static -void print_verilog_top_testbench_vanilla_bitstream(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Find Bit-Line and Word-Line port */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - /* Find Bit-Line and Word-Line port */ - ModulePortId bl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); - - ModulePortId wl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME)); - BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); - - /* Initial value should be the first configuration bits - * In the rest of programming cycles, - * configuration bits are fed at the falling edge of programming clock. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway - */ - std::vector initial_bl_values(bl_port.get_width(), 0); - std::vector initial_wl_values(wl_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Configuration chain default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(bl_port, initial_bl_values); - fp << ";" << std::endl; - fp << "\t\t"; - fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); - fp << ";" << std::endl; - - fp << std::endl; - - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ") begin" << std::endl; - - /* Enable all the WLs */ - std::vector enabled_wl_values(wl_port.get_width(), 1); - fp << "\t\t\t"; - fp << generate_verilog_port_constant_values(wl_port, enabled_wl_values); - fp << ";" << std::endl; - - size_t ibit = 0; - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - BasicPort cur_bl_port(bl_port); - cur_bl_port.set_width(ibit, ibit); - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_bl_port); - fp << " = "; - fp << "1'b" << (size_t)bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); - fp << ";" << std::endl; - - ibit++; - } - - fp << "\t\tend" << std::endl; - - /* Disable all the WLs */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); - fp << ";" << std::endl; - - /* Raise the flag of configuration done when bitstream loading is complete */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a configuration chain protocol - * where configuration bits are programming in serial (one by one) - * Task list: - * 1. For clock signal, we should create voltage waveforms for two types of clock signals: - * a. operation clock - * b. programming clock - * 2. For Set/Reset, we reset the chip after programming phase ends - * and before operation phase starts - * 3. For input/output clb nets (mapped to I/O grids), - * we should create voltage waveforms only after programming phase - *******************************************************************/ -static -void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Initial value should be the first configuration bits - * In the rest of programming cycles, - * configuration bits are fed at the falling edge of programming clock. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway - */ - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort config_chain_head_port = module_manager.module_port(top_module, cc_head_port_id); - std::vector initial_values(config_chain_head_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Configuration chain default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(config_chain_head_port, initial_values); - fp << ";"; - - fp << std::endl; - - /* Find the longest bitstream */ - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); - - /* For fast configuration, the bitstream size counts from the first bit '1' */ - size_t num_bits_to_skip = 0; - if (true == fast_configuration) { - num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); - } - VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); - - /* Reorganize the regional bitstreams to be the same size */ - ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); - - /* Attention: when the fast configuration is enabled, we will start from the first bit '1' - * This requires a reset signal (as we forced in the first clock cycle) - * - * Note that bitstream may come from different regions - * The bitstream value to be loaded should be organized as follows - * - * cycleA - * | - * Region 0: 0|00000001111101010 - * Region 1: | 00000011010101 - * Region 2: | 0010101111000110 - * - * Zero bits will be added to the head of those bitstreams are shorter - * than the longest bitstream - */ - for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { - std::vector curr_cc_head_val; - curr_cc_head_val.reserve(fabric_bitstream.regions().size()); - for (const auto& region_bitstream : regional_bitstreams) { - curr_cc_head_val.push_back((size_t)region_bitstream[ibit]); - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << generate_verilog_constant_values(curr_cc_head_val) << ");" << std::endl; - } - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a memory bank configuration protocol - * where configuration bits are programming in serial (one by one) - * - * We will use the programming task function created before - *******************************************************************/ -static -void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Feed addresss and data input pair one by one - * Note: the first cycle is reserved for programming reset - * We should give dummy values - */ - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); - std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); - - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); - std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - std::vector initial_din_values(din_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Address port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); - fp << ";"; - fp << std::endl; - - fp << "\t\t"; - fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); - fp << ";"; - fp << std::endl; - - print_verilog_comment(fp, "----- Data-input port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(din_port, initial_din_values); - fp << ";"; - - fp << std::endl; - - /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); - - for (const auto& addr_din_pair : fabric_bits_by_addr) { - /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - */ - if (true == fast_configuration) { - bool skip_curr_bits = true; - for (const bool& bit : addr_din_pair.second) { - if (bit_value_to_skip != bit) { - skip_curr_bits = false; - break; - } - } - - if (true == skip_curr_bits) { - continue; - } - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << bl_addr_port.get_width() << "'b"; - VTR_ASSERT(bl_addr_port.get_width() == addr_din_pair.first.first.length()); - fp << addr_din_pair.first.first; - - fp << ", "; - fp << wl_addr_port.get_width() << "'b"; - VTR_ASSERT(wl_addr_port.get_width() == addr_din_pair.first.second.length()); - fp << addr_din_pair.first.second; - - fp << ", "; - fp << din_port.get_width() << "'b"; - VTR_ASSERT(din_port.get_width() == addr_din_pair.second.size()); - for (const bool& din_value : addr_din_pair.second) { - if (true == din_value) { - fp << "1"; - } else { - VTR_ASSERT(false == din_value); - fp << "0"; - } - } - fp << ");" << std::endl; - } - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a frame-based configuration protocol - * where configuration bits are programming in serial (one by one) - * - * We will use the programming task function created before - *******************************************************************/ -static -void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Feed addresss and data input pair one by one - * Note: the first cycle is reserved for programming reset - * We should give dummy values - */ - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); - std::vector initial_addr_values(addr_port.get_width(), 0); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - std::vector initial_din_values(din_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Address port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(addr_port, initial_addr_values); - fp << ";"; - fp << std::endl; - - print_verilog_comment(fp, "----- Data-input port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(din_port, initial_din_values); - fp << ";"; - - fp << std::endl; - - /* Reorganize the fabric bitstream by the same address across regions */ - FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); - - for (const auto& addr_din_pair : fabric_bits_by_addr) { - /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - */ - if (true == fast_configuration) { - bool skip_curr_bits = true; - for (const bool& bit : addr_din_pair.second) { - if (bit_value_to_skip != bit) { - skip_curr_bits = false; - break; - } - } - - if (true == skip_curr_bits) { - continue; - } - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << addr_port.get_width() << "'b"; - VTR_ASSERT(addr_port.get_width() == addr_din_pair.first.size()); - fp << addr_din_pair.first; - fp << ", "; - fp << din_port.get_width() << "'b"; - VTR_ASSERT(din_port.get_width() == addr_din_pair.second.size()); - for (const bool& din_value : addr_din_pair.second) { - if (true == din_value) { - fp << "1"; - } else { - VTR_ASSERT(false == din_value); - fp << "0"; - } - } - fp << ");" << std::endl; - } - - /* Disable the address and din - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << addr_port.get_width() << "'b"; - std::vector all_zero_addr(addr_port.get_width(), 0); - for (const size_t& addr_bit : all_zero_addr) { - fp << addr_bit; - } - fp << ", "; - fp << generate_verilog_constant_values(initial_din_values); - fp << ");" << std::endl; - */ - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Generate the stimuli for the top-level testbench - * The simulation consists of two phases: configuration phase and operation phase - * Configuration bits are loaded serially. - * This is actually what we do for a physical FPGA - *******************************************************************/ -static -void print_verilog_top_testbench_bitstream(std::fstream& fp, - const e_config_protocol_type& config_protocol_type, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - - /* Branch on the type of configuration protocol */ - switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - print_verilog_top_testbench_vanilla_bitstream(fp, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - break; - case CONFIG_MEM_SCAN_CHAIN: - print_verilog_top_testbench_configuration_chain_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_top_testbench_memory_bank_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_top_testbench_frame_decoder_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization type!\n"); - exit(1); - } -} - /******************************************************************** * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol * We will load the bitstream in the second clock cycle, right after the first reset cycle @@ -2534,263 +1840,6 @@ void print_verilog_top_testbench_check(std::fstream& fp, fp << std::endl; } -/******************************************************************** - * TODO: This top function will be deprecated!!! The only top function is - * print_verilog_full_testbench() - * The top-level function to generate a testbench, in order to verify: - * 1. Configuration phase of the FPGA fabric, where the bitstream is - * loaded to the configuration protocol of the FPGA fabric - * 2. Operating phase of the FPGA fabric, where input stimuli are - * fed to the I/Os of the FPGA fabric - * +----------+ - * | FPGA | +------------+ - * +----->| Fabric |------>| | - * | | | | | - * | +----------+ | | - * | | Output | - * random_input_vectors -----+ | Vector |---->Functional correct? - * | | Comparator | - * | +-----------+ | | - * | | Input | | | - * +----->| Benchmark |----->| | - * +-----------+ +------------+ - * - *******************************************************************/ -void print_verilog_top_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options) { - - bool fast_configuration = options.fast_configuration(); - bool explicit_port_mapping = options.explicit_port_mapping(); - - std::string timer_message = std::string("Write autocheck testbench for FPGA top-level Verilog netlist for '") + circuit_name + std::string("'"); - - /* Start time count */ - vtr::ScopedStartFinishTimer timer(timer_message); - - /* Create the file stream */ - std::fstream fp; - fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); - - /* Validate the file stream */ - check_file_stream(verilog_fname.c_str(), fp); - - /* Generate a brief description on the Verilog file*/ - std::string title = std::string("FPGA Verilog Testbench for Top-level netlist of Design: ") + circuit_name; - print_verilog_file_header(fp, title); - - /* Find the top_module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - - /* Preparation: find all the clock ports */ - std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); - - /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); - std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); - - /* Identify if we can apply fast configuration */ - bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); - bool bit_value_to_skip = false; - if (true == apply_fast_configuration) { - bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); - } - - /* Start of testbench */ - print_verilog_top_testbench_ports(fp, module_manager, top_module, - atom_ctx, netlist_annotation, - clock_port_names, - pin_constraints, - simulation_parameters, config_protocol, - circuit_name); - - /* Find the clock period */ - float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); - float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency()); - float max_op_clock_period = 0.; - for (const SimulationClockId& clock_id : simulation_parameters.clocks()) { - max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id))); - } - - /* Estimate the number of configuration clock cycles */ - size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(), - apply_fast_configuration, - bit_value_to_skip, - bitstream_manager, - fabric_bitstream); - - /* Generate stimuli for general control signals */ - print_verilog_top_testbench_generic_stimulus(fp, - simulation_parameters, - num_config_clock_cycles, - prog_clock_period, - default_op_clock_period, - VERILOG_SIM_TIMESCALE); - - /* Generate stimuli for programming interface */ - print_verilog_top_testbench_configuration_protocol_stimulus(fp, - config_protocol.type(), - module_manager, top_module, - prog_clock_period, - VERILOG_SIM_TIMESCALE); - - /* Identify the stimulus for global reset/set for programming purpose: - * - If only reset port is seen we turn on Reset - * - If only set port is seen we turn on Reset - * - If both reset and set port is defined, - * we pick the one which is consistent with the bit value to be skipped - */ - bool active_global_prog_reset = false; - bool active_global_prog_set = false; - - if (!global_prog_reset_ports.empty()) { - active_global_prog_reset = true; - } - - if (!global_prog_set_ports.empty()) { - active_global_prog_set = true; - } - - /* Ensure that at most only one of the two switches is activated */ - if ( (true == active_global_prog_reset) - && (true == active_global_prog_set) ) { - /* If we will skip logic '0', we will activate programming reset */ - active_global_prog_reset = !bit_value_to_skip; - /* If we will skip logic '1', we will activate programming set */ - active_global_prog_set = bit_value_to_skip; - } - - /* Generate stimuli for global ports or connect them to existed signals */ - print_verilog_top_testbench_global_ports_stimuli(fp, - module_manager, top_module, - pin_constraints, - global_ports, - simulation_parameters, - active_global_prog_reset, - active_global_prog_set); - - /* Instanciate FPGA top-level module */ - print_verilog_testbench_fpga_instance(fp, module_manager, top_module, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - explicit_port_mapping); - - /* Connect I/Os to benchmark I/Os or constant driver */ - print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, - atom_ctx, place_ctx, io_location_map, - netlist_annotation, - std::string(), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); - - /* Instanciate input benchmark */ - print_verilog_top_testbench_benchmark_instance(fp, - circuit_name, - atom_ctx, - netlist_annotation, - explicit_port_mapping); - - /* Print tasks used for loading bitstreams */ - print_verilog_top_testbench_load_bitstream_task(fp, - config_protocol.type(), - module_manager, top_module); - - /* load bitstream to FPGA fabric in a configuration phase */ - print_verilog_top_testbench_bitstream(fp, config_protocol.type(), - apply_fast_configuration, - bit_value_to_skip, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - - /* Add signal initialization: - * Bypass writing codes to files due to the autogenerated codes are very large. - */ - if (true == options.include_signal_init()) { - print_verilog_testbench_signal_initialization(fp, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - circuit_lib, - module_manager, - top_module); - } - - - /* Add stimuli for reset, set, clock and iopad signals */ - print_verilog_top_testbench_reset_stimuli(fp, - atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names); - print_verilog_testbench_random_stimuli(fp, atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names, - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::vector(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1))); - - /* Add output autocheck */ - print_verilog_testbench_check(fp, - std::string(AUTOCHECKED_SIMULATION_FLAG), - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::string(TOP_TESTBENCH_ERROR_COUNTER), - atom_ctx, - netlist_annotation, - clock_port_names, - std::string(TOP_TB_OP_CLOCK_PORT_NAME)); - - /* Add autocheck for configuration phase */ - print_verilog_top_testbench_check(fp, - std::string(AUTOCHECKED_SIMULATION_FLAG), - std::string(TOP_TB_CONFIG_DONE_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER)); - - /* Find simulation time */ - float simulation_time = find_simulation_time_period(VERILOG_SIM_TIMESCALE, - num_config_clock_cycles, - 1./simulation_parameters.programming_clock_frequency(), - simulation_parameters.num_clock_cycles(), - 1./simulation_parameters.default_operating_clock_frequency()); - - - /* Add Icarus requirement: - * Always ceil the simulation time so that we test a sufficient length of period!!! - */ - print_verilog_timeout_and_vcd(fp, - std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), - std::string(circuit_name + std::string("_formal.vcd")), - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER), - std::ceil(simulation_time)); - - - /* Testbench ends*/ - print_verilog_module_end(fp, std::string(circuit_name) + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)); - - /* Close the file stream */ - fp.close(); -} - /******************************************************************** * The top-level function to generate a full testbench, in order to verify: * 1. Configuration phase of the FPGA fabric, where the bitstream is diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index 1704d0dd5..aff108d72 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -26,22 +26,6 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_top_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options); - int print_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, From d9d57aad427a0a1d53efd9b758e0a295dec0b186 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 14 Jun 2021 11:37:49 -0600 Subject: [PATCH 325/352] [Tool] Added default net type options to verilog testbench generator command --- openfpga/src/base/openfpga_verilog.cpp | 12 ++++++++++++ .../src/base/openfpga_verilog_command.cpp | 12 ++++++++++++ openfpga/src/fpga_verilog/verilog_api.cpp | 4 ++-- .../verilog_formal_random_top_testbench.cpp | 13 +++++++------ .../verilog_formal_random_top_testbench.h | 3 ++- .../verilog_preconfig_top_module.cpp | 6 +++--- .../verilog_preconfig_top_module.h | 3 ++- .../verilog_testbench_options.cpp | 19 +++++++++++++++++++ .../fpga_verilog/verilog_testbench_options.h | 4 ++++ .../fpga_verilog/verilog_top_testbench.cpp | 8 +++++--- 10 files changed, 68 insertions(+), 16 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index e279f1200..081466c06 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -74,6 +74,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); CommandOptionId opt_fast_configuration = cmd.option("fast_configuration"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -89,6 +90,9 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_top_testbench(true); options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { + options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + } /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; @@ -122,6 +126,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); CommandOptionId opt_verbose = cmd.option("verbose"); @@ -135,6 +140,9 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); options.set_print_formal_verification_top_netlist(true); + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { + options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + } /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; @@ -167,6 +175,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_verbose = cmd.option("verbose"); /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog @@ -180,6 +189,9 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_preconfig_top_testbench(true); + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { + options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + } /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 174b8a4d7..a890d6971 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -93,6 +93,10 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell& clock_port_names, const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation) { + const VprNetlistAnnotation& netlist_annotation, + const e_verilog_default_net_type& default_net_type) { /* Validate the file stream */ valid_file_stream(fp); print_verilog_default_net_type_declaration(fp, - VERILOG_DEFAULT_NET_TYPE_NONE); + default_net_type); /* Print the declaration for the module */ fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" << std::endl; @@ -278,7 +279,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, const FabricGlobalPortInfo& global_ports, const PinConstraints& pin_constraints, const SimulationSetting& simulation_parameters, - const bool& explicit_port_mapping) { + const VerilogTestbenchOption &options) { std::string timer_message = std::string("Write configuration-skip testbench for FPGA top-level Verilog netlist implemented by '") + circuit_name.c_str() + std::string("'"); /* Start time count */ @@ -299,17 +300,17 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); /* Start of testbench */ - print_verilog_top_random_testbench_ports(fp, circuit_name, clock_port_names, atom_ctx, netlist_annotation); + print_verilog_top_random_testbench_ports(fp, circuit_name, clock_port_names, atom_ctx, netlist_annotation, options.default_net_type()); /* Call defined top-level module */ print_verilog_random_testbench_fpga_instance(fp, circuit_name, atom_ctx, netlist_annotation, - explicit_port_mapping); + options.explicit_port_mapping()); /* Call defined benchmark */ print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name, atom_ctx, netlist_annotation, - explicit_port_mapping); + options.explicit_port_mapping()); /* Find clock port to be used */ std::vector clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME)); diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h index 6dd4f0310..d58bae969 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h @@ -10,6 +10,7 @@ #include "module_manager.h" #include "fabric_global_port_info.h" #include "simulation_setting.h" +#include "verilog_testbench_options.h" /******************************************************************** * Function declaration @@ -26,7 +27,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, const FabricGlobalPortInfo& global_ports, const PinConstraints& pin_constraints, const SimulationSetting& simulation_parameters, - const bool& explicit_port_mapping); + const VerilogTestbenchOption &options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index ece6df67a..5b7264044 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -442,7 +442,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager, const VprNetlistAnnotation &netlist_annotation, const std::string &circuit_name, const std::string &verilog_fname, - const bool &explicit_port_mapping) { + const VerilogTestbenchOption& options) { std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'"); int status = CMD_EXEC_SUCCESS; @@ -462,7 +462,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager, print_verilog_file_header(fp, title); print_verilog_default_net_type_declaration(fp, - VERILOG_DEFAULT_NET_TYPE_NONE); + options.default_net_type()); /* Print module declaration and ports */ print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation); @@ -477,7 +477,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager, /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance(fp, module_manager, top_module, std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), - explicit_port_mapping); + options.explicit_port_mapping()); /* Find clock ports in benchmark */ std::vector benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index ff82dea94..01bb12f08 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -15,6 +15,7 @@ #include "fabric_global_port_info.h" #include "config_protocol.h" #include "vpr_netlist_annotation.h" +#include "verilog_testbench_options.h" /******************************************************************** * Function declaration @@ -35,7 +36,7 @@ int print_verilog_preconfig_top_module(const ModuleManager& module_manager, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, - const bool& explicit_port_mapping); + const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp index b39adef43..cce9338cf 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp @@ -23,6 +23,7 @@ VerilogTestbenchOption::VerilogTestbenchOption() { explicit_port_mapping_ = false; support_icarus_simulator_ = false; include_signal_init_ = false; + default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE; verbose_output_ = false; } @@ -77,6 +78,10 @@ bool VerilogTestbenchOption::support_icarus_simulator() const { return support_icarus_simulator_; } +e_verilog_default_net_type VerilogTestbenchOption::default_net_type() const { + return default_net_type_; +} + bool VerilogTestbenchOption::verbose_output() const { return verbose_output_; } @@ -141,6 +146,20 @@ void VerilogTestbenchOption::set_support_icarus_simulator(const bool& enabled) { support_icarus_simulator_ = enabled; } +void VerilogTestbenchOption::set_default_net_type(const std::string& default_net_type) { + /* Decode from net type string */; + if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) { + default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE; + } else if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE])) { + default_net_type_ = VERILOG_DEFAULT_NET_TYPE_WIRE; + } else { + VTR_LOG_WARN("Invalid default net type: '%s'! Expect ['%s'|'%s']\n", + default_net_type.c_str(), + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE], + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]); + } +} + void VerilogTestbenchOption::set_verbose_output(const bool& enabled) { verbose_output_ = enabled; } diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.h b/openfpga/src/fpga_verilog/verilog_testbench_options.h index 492740f8e..6b46d8316 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.h @@ -5,6 +5,7 @@ * Include header files required by the data structure definition *******************************************************************/ #include +#include "verilog_port_types.h" /* Begin namespace openfpga */ namespace openfpga { @@ -34,6 +35,7 @@ class VerilogTestbenchOption { bool explicit_port_mapping() const; bool include_signal_init() const; bool support_icarus_simulator() const; + e_verilog_default_net_type default_net_type() const; bool verbose_output() const; public: /* Public validator */ bool validate() const; @@ -58,6 +60,7 @@ class VerilogTestbenchOption { void set_explicit_port_mapping(const bool& enabled); void set_include_signal_init(const bool& enabled); void set_support_icarus_simulator(const bool& enabled); + void set_default_net_type(const std::string& default_net_type); void set_verbose_output(const bool& enabled); private: /* Internal Data */ std::string output_directory_; @@ -72,6 +75,7 @@ class VerilogTestbenchOption { bool explicit_port_mapping_; bool support_icarus_simulator_; bool include_signal_init_; + e_verilog_default_net_type default_net_type_; bool verbose_output_; }; diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 779b6ceaa..aecf72d6f 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -701,12 +701,13 @@ void print_verilog_top_testbench_ports(std::fstream& fp, const PinConstraints& pin_constraints, const SimulationSetting& simulation_parameters, const ConfigProtocol& config_protocol, - const std::string& circuit_name){ + const std::string& circuit_name, + const e_verilog_default_net_type& default_net_type) { /* Validate the file stream */ valid_file_stream(fp); print_verilog_default_net_type_declaration(fp, - VERILOG_DEFAULT_NET_TYPE_NONE); + default_net_type); /* Print module definition */ fp << "module " << circuit_name << std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX); @@ -1923,7 +1924,8 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, clock_port_names, pin_constraints, simulation_parameters, config_protocol, - circuit_name); + circuit_name, + options.default_net_type()); /* Find the clock period */ float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); From d40cf98c4833ca170b53f597f82c754121ea61c9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 14 Jun 2021 11:47:28 -0600 Subject: [PATCH 326/352] [Test] Update test cases by using default net type in testbench generator --- .../behavioral_verilog_example_script.openfpga | 4 ++-- .../implicit_verilog_example_script.openfpga | 6 +++--- .../verilog_default_net_type_example_script.openfpga | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga index d27d4eff6..cf614678e 100644 --- a/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/behavioral_verilog_example_script.openfpga @@ -55,8 +55,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --default_net_type ${OPENFPGA_VERILOG_DEFAULT_NET_TYPE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator --default_net_type ${OPENFPGA_VERILOG_DEFAULT_NET_TYPE} # Finish and exit OpenFPGA exit diff --git a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga index c0752db76..9a32a86eb 100644 --- a/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga @@ -55,9 +55,9 @@ write_fabric_verilog --file ./SRC --include_timing --print_user_defined_template # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit -write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --bitstream fabric_bitstream.bit --default_net_type ${OPENFPGA_DEFAULT_NET_TYPE} +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --default_net_type ${OPENFPGA_DEFAULT_NET_TYPE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator --default_net_type ${OPENFPGA_DEFAULT_NET_TYPE} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga index 77f01d371..fab25be5a 100644 --- a/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/verilog_default_net_type_example_script.openfpga @@ -55,9 +55,9 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit -write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit --default_net_type ${OPENFPGA_VERILOG_DEFAULT_NET_TYPE} +write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping --default_net_type ${OPENFPGA_VERILOG_DEFAULT_NET_TYPE} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator --default_net_type ${OPENFPGA_VERILOG_DEFAULT_NET_TYPE} # Write the SDC files for PnR backend # - Turn on every options here From dc1332563914e67b2c52aaf9c7730048a4f84655 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 14 Jun 2021 13:44:20 -0600 Subject: [PATCH 327/352] Update motivation.rst Fixing grammar and spacing --- docs/source/overview/motivation.rst | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/source/overview/motivation.rst b/docs/source/overview/motivation.rst index 0fc4d58cb..a7315ef52 100644 --- a/docs/source/overview/motivation.rst +++ b/docs/source/overview/motivation.rst @@ -1,13 +1,13 @@ Why OpenFPGA? ------------- -.. note:: If this is the first time you learn OpenFPGA, we strongly recommend you to watch the `introduction video `_ +.. note:: If this is your first time learning OpenFPGA, we strongly recommend you to watch the `introduction video `_ .. only:: html .. youtube:: ocODUGcYGqo -OpenFPGA aims to be an open-source framework that enables rapid prototyping of customizable FPGA architectures. As shown in :numref:`fig_openfpga_motivation`, a conventional approach will take a large group of experienced engineers more than one year to achieve production-ready layout and assoicated CAD tools. In fact, most of the engineering efforts are spent on manual layouts and developing ad-hoc CAD support. +OpenFPGA aims to be an open-source framework that enables rapid prototyping of customizable FPGA architectures. As shown in :numref:`fig_openfpga_motivation`, a conventional approach will take a large group of experienced engineers more than one year to achieve production-ready layout and associated CAD tools. In fact, most of the engineering efforts are spent on manual layouts and developing ad-hoc CAD support. .. _fig_openfpga_motivation: @@ -15,15 +15,15 @@ OpenFPGA aims to be an open-source framework that enables rapid prototyping of c :scale: 50% :alt: OpenFPGA: a fast prototyping framework for customizable FPGAs - Comparison on engineering time and effort to prototype an FPGA using OpenFPGA and conventional approaches [All the layout figures are permitted to publish under proper licenses] + Comparison on engineering time and effort to prototype an FPGA using OpenFPGA and conventional approaches [All the layout figures are publishable under the proper licenses] Using OpenFPGA, the development cycle in both hardware and software can be significantly accelerated. OpenFPGA can automatically generate Verilog netlists describing a full FPGA fabric based on an XML-based description file. Thanks to modern semi-custom design tools, production-ready layout generation can be achieved within 24 hours. To help sign-off, OpenFPGA can auto-generate Verilog testbenches to validate the correctness of FPGA fabric using modern verification tools. -OpenFPGA also provides native bitstream generation support based the same XML-based description file used in Verilog generation. This avoid the recurring engineering in developing CAD tools for different FPGAs. Once the FPGA architecture is finalized, the CAD tool is ready to use. +OpenFPGA also provides native bitstream generation support based on the same XML-based description file used in Verilog generation, avoiding the recurring engineering in developing CAD tools for different FPGAs. Once the FPGA architecture is finalized, the CAD tool is ready to use. -OpenFPGA can support any architecture that VPR can describe, covering most of the architecture enhancements available in modern FPGAs, and hence unlocks a large design space in prototyping customizable FPGAs. In addition, OpenFPGA provides enriched syntax which allows users to customized primitive circuit designed downto transistor-level parameters. This helps developers to customize the P.P.A. (Power, Performance and Area) to the best. All these features open the door of prototyping/studying flexible FPGAs to a small group of junior engineers or researchers. +OpenFPGA can support any architecture that VPR can describe, covering most of the architecture enhancements available in modern FPGAs, and hence unlocks a large design space in prototyping customizable FPGAs. In addition, OpenFPGA provides enriched syntax which allows users to customize primitive circuits designed down to transistor-level parameters. This helps developers to customize the P.P.A. (Power, Performance and Area) to the best. All these features open the door of prototyping/studying flexible FPGAs to a small group of junior engineers or researchers. In terms of tool functionality, OpenFPGA consists of the following parts: FPGA-Verilog, FPGA-SDC, FPGA-Bitstream and FPGA-SPICE. -The rest of this section will focus on detailed motivation on each of them, as depicted in :numref:`fig_openfpga_framework`. +The rest of this section will focus on detailed motivation for each of them, as depicted in :numref:`fig_openfpga_framework`. .. _fig_openfpga_framework: @@ -39,7 +39,7 @@ Fully Customizable Architecture OpenFPGA supports VPR's architecture description language, which allows users to define versatile programmable fabrics down to point-to-point interconnection. -OpenFPGA leverage VPR's architecture description by introducing an XML-based +OpenFPGA leverages VPR's architecture description by introducing an XML-based architecture annotation, enabling fully customizable FPGA fabric down to circuit elements. As illustrated in :ref:`fig_openfpga_arch_lang_coverage`, OpenFPGA's @@ -60,7 +60,9 @@ FPGA-Verilog ~~~~~~~~~~~~ Driven by the strong need in data processing applications, Field Programmable Gate Arrays (FPGAs) are playing an ever-increasing role as programmable accelerators in modern -computing systems. To fully unlock processing capabilities for domain-specific applications, FPGA architectures have to be tailored for seamless cooperation with other computing resources. However, prototyping and bringing to production a customized FPGA is a costly and complex endeavor even for industrial vendors. OpenFPGA, an opensource framework, aims to rapid prototype of customizable FPGA architectures through a semi-custom design approach. We propose an XML-to-Prototype design flow, where the Verilog netlists of a full FPGA fabric can be autogenerated using an extension of the XML language from the VTR framework and then fed into a back-end flow to generate production-ready layouts. +computing systems. To fully unlock processing capabilities for domain-specific applications, FPGA architectures have to be tailored for seamless cooperation with other computing resources. However, prototyping and bringing to production a customized FPGA is a costly and complex endeavor even for industrial vendors. + +OpenFPGA, an opensource framework, aims to rapidly prototype customizable FPGA architectures through a semi-custom design approach. We propose an XML-to-Prototype design flow, where the Verilog netlists of a full FPGA fabric can be autogenerated using an extension of the XML language from the VTR framework and then fed into a back-end flow to generate production-ready layouts. FPGA-Verilog is designed to output flexible and standard Verilog netlists, enabling various backend choices, as illustrated in :ref:`fig_fpga_verilog_motivation`. .. _fig_fpga_verilog_motivation: @@ -80,7 +82,7 @@ Design constraints are indepensible in modern ASIC design flows to guarantee the OpenFPGA includes a rich SDC generator in the OpenFPGA framework to deal with both PnR constraints and sign-off timing analysis. Our flow automatically generates two sets of SDC files. -- The first set of SDC is designed for the P&R flow, where all the combinational loops are broken to enable wellcontrolled timing-driven P&R. In addition, there are SDC files devoted to constrain pin-to-pin timing for all the resources in FPGAs, in order to obtain nicely constrained and homogeneous delays across the fabric. OpenFPGA allows users to define timing constraints in the architecture description and outputs timing constraints in standard format, enabling fully timing constrained backend flow (see :ref:`fig_fpga_sdc_motivation`). +- The first set of SDC is designed for the P&R flow, where all the combinational loops are broken to enable well controlled timing-driven P&R. In addition, there are SDC files devoted to constrain pin-to-pin timing for all the resources in FPGAs, in order to obtain nicely constrained and homogeneous delays across the fabric. OpenFPGA allows users to define timing constraints in the architecture description and outputs timing constraints in standard format, enabling fully timing constrained backend flow (see :ref:`fig_fpga_sdc_motivation`). - The second set of SDC is designed for the timing analysis of a benchmark at the post P&R stage. .. _fig_fpga_sdc_motivation: @@ -98,20 +100,18 @@ The technical details can be found in our FPL'19 paper :cite:`XTang_FPL_2019`. FPGA-Bitstream ~~~~~~~~~~~~~~ -EDA support is essential for end-users to implement designs on a customized FPGA. OpenFPGA provides a general-purpose bitstream generator FPGA-Bitstream for any architecture that can be described by VPR. As the native CAD tool for any customized FPGA that is produced by FPGA-Verilog, FPGA-Bitstream is ready to use once users finalize the XML-based architecture description file. This eliminates the huge engineering efforts spent on developing bitstream generator for customized FPGAs. - -Using FPGA-Bitstream, users can launch (1) Verilog-to-Bitstream flow. This is the typical implementation flow for end-users; (2) Verilog-to-Verification flow. OpenFPGA can output Verilog testbenches with self-testing features to validate users' implemetations on their customized FPGA fabrics. +EDA support is essential for end-users to implement designs on a customized FPGA. OpenFPGA provides a general-purpose bitstream generator FPGA-Bitstream for any architecture that can be described by VPR. As the native CAD tool for any customized FPGA that is produced by FPGA-Verilog, FPGA-Bitstream is ready to use once users finalize the XML-based architecture description file. This eliminates the huge engineering efforts spent on developing bitstream generators for customized FPGAs. Using FPGA-Bitstream, users can launch (1) Verilog-to-Bitstream flow, the typical implementation flow for end-users; (2) Verilog-to-Verification flow. OpenFPGA can output Verilog testbenches with self-testing features to validate users' implemetations on their customized FPGA fabrics. The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019` and FPL'19 paper :cite:`XTang_FPL_2019`. FPGA-SPICE ~~~~~~~~~~ -The built-in timing and power analysis engines of VPR are based on analytical models :cite:`VBetz_Book_1999,JGoeders_FPT_2012`. Analytical model-based analysis can promise accuracy only on a limited number of circuit designs for which the model is valid. As the technology advancements create more opportunities on circuit designs and FPGA architectures, the analytical power model require to be updated to follow the new trends. However, without referring to simulation results, the analytical power models cannot prove their accuracy. SPICE simulators have the advantages of generality and accuracy over analytical models. For this reason, SPICE simulation results are often selected to check the accuracy of analytical models. Therefore, there is a strong need for a simulation-based power analysis approach for FPGAs, which can support general circuit designs. +The built-in timing and power analysis engines of VPR are based on analytical models :cite:`VBetz_Book_1999,JGoeders_FPT_2012`. Analytical model-based analysis can promise accuracy only on a limited number of circuit designs for which the model is valid. As the technology advancements create more opportunities on circuit designs and FPGA architectures, the analytical power model requires updates to follow the new trends. However, without referring to simulation results, the analytical power models cannot prove their accuracy. SPICE simulators have the advantages of generality and accuracy over analytical models. For this reason, SPICE simulation results are often selected to check the accuracy of analytical models. Therefore, there is a strong need for a simulation-based power analysis approach for FPGAs, which can support general circuit designs. It motivates us to develop FPGA-SPICE, an add-on for the current State-of-Art FPGA architecture exploration tools, VPR :cite:`JRose_FPGA_2012`. -FPGA-SPICE aims at generating SPICE netlists and testbenches for the FPGA architectures supported by VPR. The SPICE netlists and testbenches are generated according to the placement and routing results of VPR. As a result, SPICE simulator can be used to perform precise delay and power analysis. The SPICE simulation results are useful in three aspects: (1) it can provide accurate power analysis; (2) it helps to improve the accuracy of built-in analytical models; and moreover (3) it creates opportunities in developing novel analytical models. +FPGA-SPICE aims at generating SPICE netlists and testbenches for the FPGA architectures supported by VPR. The SPICE netlists and testbenches are generated according to the placement and routing results of VPR. As a result, SPICE simulator can be used to perform precise delay and power analysis. The SPICE simulation results are useful in three aspects: (1) they provide accurate power analysis; (2) they help to improve the accuracy of built-in analytical models; and moreover (3) they create opportunities in developing novel analytical models. -SPICE modeling for FPGA architectures requires detailed transistor-level modeling for all the circuit elements within the considered FPGA architecture. However, current VPR architectural description language :cite:`JLuu_FPGA_2011` does not offer enough transistor-level parameters to model the most common circuit modules, such as multiplexers and LUTs. Therefore, we develop an extension on the VPR architectural description language to model the transistor-level circuit designs. +SPICE modeling for FPGA architectures requires detailed transistor-level modeling for all the circuit elements within the considered FPGA architecture. However, current VPR architectural description language :cite:`JLuu_FPGA_2011` does not offer enough transistor-level parameters to model the most common circuit modules, such as multiplexers and LUTs. Therefore, we are developing an extension on the VPR architectural description language to model the transistor-level circuit designs. The technical details can be found in our ICCD’15 paper :cite:`XTang_ICCD_2015` and TVLSI'19 paper :cite:`XTang_TVLSI_2019`. From 9585e1d3b5f94e78a3802c8ed64675180fcd647f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 14 Jun 2021 14:00:34 -0600 Subject: [PATCH 328/352] [Doc] Update documentation about 'default_net_type' option in testbench generators --- .../openfpga_commands/fpga_verilog_commands.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index 5c57d104e..2a9af3b96 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -76,6 +76,10 @@ write_full_testbench Use explicit port mapping when writing the Verilog netlists + .. option:: --default_net_type + + Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``. + .. option:: --include_signal_init Output signal initialization to Verilog testbench to smooth convergence in HDL simulation @@ -106,6 +110,10 @@ write_preconfigured_fabric_wrapper Use explicit port mapping when writing the Verilog netlists + .. option:: --default_net_type + + Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``. + .. option:: --support_icarus_simulator Output Verilog netlists with syntax that iVerilog simulator can accept @@ -140,6 +148,11 @@ write_preconfigured_testbench Use explicit port mapping when writing the Verilog netlists + .. option:: --default_net_type + + Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``. + + .. option:: --support_icarus_simulator Output Verilog netlists with syntax that iVerilog simulator can accept From d0549f10b36aa89553f9bf8b6d63e4d08eac7998 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 14 Jun 2021 14:28:21 -0600 Subject: [PATCH 329/352] Make a :ref: for tutorial --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 2255c22f0..d8dab55b0 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -1,3 +1,5 @@ +.. _standard_cell_tutorial: + Build an FPGA fabric using Standard Cell Libraries ================================================== From 1a2ced678edf2a8781caf37f1366774f11d7a1da Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 14 Jun 2021 14:34:12 -0600 Subject: [PATCH 330/352] Update tech_highlights.rst Update grammar and add link to standard_cell_library tutorial --- docs/source/overview/tech_highlights.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/overview/tech_highlights.rst b/docs/source/overview/tech_highlights.rst index 95521cc29..1f4cd8b61 100644 --- a/docs/source/overview/tech_highlights.rst +++ b/docs/source/overview/tech_highlights.rst @@ -1,7 +1,7 @@ Technical Highlights -------------------- -The follow lists of technical features are created to help users spot their needs in customizing FPGA fabrics.(**as of February 2021**) +The following lists of technical features were created to help users find their needs for customizing FPGA fabrics.(**as of February 2021**) Supported Circuit Designs ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -62,13 +62,13 @@ Supported Circuit Designs +-----------------+--------------+-----------+-----------------------------------------------------+ -* The user defined netlist could come from a standard cell +* The user defined netlist could come from a standard cell. See :ref:`standard_cell_tutorial` for details. Supported FPGA Architectures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We support most FPGA architectures that VPR can support! -The following are most commonly seen architectural features: +The following are the most commonly seen architectural features: +------------------------+----------------------------------------------+ | Block Type | Architecture features | From 5e8b5d641f6e20c9fc89f502a33b705a7fdf58bf Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 14 Jun 2021 14:51:19 -0600 Subject: [PATCH 331/352] Update compile.rst update grammar --- docs/source/tutorials/getting_started/compile.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/tutorials/getting_started/compile.rst b/docs/source/tutorials/getting_started/compile.rst index 8b95c995d..37223ed6c 100644 --- a/docs/source/tutorials/getting_started/compile.rst +++ b/docs/source/tutorials/getting_started/compile.rst @@ -24,13 +24,13 @@ In general, please follow the steps to compile .. note:: cmake3.12+ is recommended to compile OpenFPGA with GUI -.. note:: recommand to use ``make -j`` to accelerate the compilation +.. note:: recommend using ``make -j`` to accelerate the compilation .. note:: VPR's GUI requires gtk-3, and can be enabled with ``cmake .. -DVPR_USE_EZGL=on`` **Quick Compilation Verification** -To quickly verify the tool is well compiled, user can run the following command from OpenFPGA root repository +To quickly verify the tool is well compiled, users can run the following command from OpenFPGA root repository .. code-block:: shell @@ -38,7 +38,7 @@ To quickly verify the tool is well compiled, user can run the following command Dependencies ~~~~~~~~~~~~ -Full list of dependencies can be found at install_dependencies_build_ +Full list of dependencies can be found at install_dependencies_build_. In particular, OpenFPGA requires specific versions for the following dependencies: :cmake: @@ -53,8 +53,8 @@ In particular, OpenFPGA requires specific versions for the following dependencie Running with the docker image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Users can skip the traditional installation process by using Dockerized version -of the OpenFPGA tool. OpenFPGA project maintains the docker image/Github package of +Users can skip the traditional installation process by using the Dockerized version +of the OpenFPGA tool. The OpenFPGA project maintains the docker image/Github package of the latest stable version of OpenFPGA in the following repository `openfpga-master `_. This image contains precompiled OpenFPGA binaries with all prerequisites installed. @@ -76,4 +76,4 @@ This image contains precompiled OpenFPGA binaries with all prerequisites install .. note:: While running local task using docker, make sure all the additional files - are maintained in the task_directory and reference using variable ${TASK_DIR} \ No newline at end of file + are maintained in the task_directory and reference using variable ${TASK_DIR} From 7a303463c378d176a3aa4d8e9b68f5a0f1947d7b Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Mon, 14 Jun 2021 15:34:13 -0600 Subject: [PATCH 332/352] Update shell_shortcuts.rst Update grammar. <_openfpga_task_args> no longer works --- docs/source/tutorials/getting_started/shell_shortcuts.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/getting_started/shell_shortcuts.rst b/docs/source/tutorials/getting_started/shell_shortcuts.rst index d8b8369e3..8671d9208 100644 --- a/docs/source/tutorials/getting_started/shell_shortcuts.rst +++ b/docs/source/tutorials/getting_started/shell_shortcuts.rst @@ -22,13 +22,13 @@ Once the ``openfpga.sh`` script is sourced, you can run any of the following com .. option:: run-task **kwarags - This command runs the specified task listed from the ``list-task`` command or from the existing directory. The command name is relative to the ``TASK_DIRECTORY``. User can provide any additional arguments which are listed `here <_openfpga_task_args>`_ to this command. + This command runs the specified task listed from the ``list-task`` command or from the existing directory. The command name is relative to the ``TASK_DIRECTORY``. Users can provide any additional arguments which are listed `here <_openfpga_task_args>`_ to this command. .. option:: run-modelsim This command runs the verification using ModelSim. The test benches are generated during the OpenFPGA run. - **Note**: user need to have ``VSIM`` install and configured + **Note**: users need to have ``VSIM`` installed and configured .. option:: run-regression-local From ece6e92f0675286584edc8bff669abd8fdce9f1e Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:29:17 -0600 Subject: [PATCH 333/352] Add video at top of page --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index ea874f15f..fedcd0b5e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -1,5 +1,12 @@ +.. tutorial_user_def_temp: + Integrating Custom Verilog Modules with user_defined_template.v ================================================================ + +.. only:: html + + .. youtube:: YTggSZHsTjg + Introduction and Setup ~~~~~~~~~~~~~~~~~~~~~~ **In this tutorial, we will** From 624e9f3bb76a2a7e262055f288c03afe041996c1 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:44:01 -0600 Subject: [PATCH 334/352] Update notation at top to match pages in doc --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index d8dab55b0..10dfd96b0 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -1,4 +1,4 @@ -.. _standard_cell_tutorial: +.. _tutorial_standard_cell: Build an FPGA fabric using Standard Cell Libraries ================================================== From 858bb2f21ec16a812ee1debd05137726990b2388 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:45:04 -0600 Subject: [PATCH 335/352] fix mistake in first line of page --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index fedcd0b5e..f2ba6e4bf 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -1,4 +1,4 @@ -.. tutorial_user_def_temp: +.. _tutorial_user_def_temp: Integrating Custom Verilog Modules with user_defined_template.v ================================================================ From 7787fe9795feec1f31e61e19173306bfe530eed9 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:46:43 -0600 Subject: [PATCH 336/352] update reference to match doc page --- docs/source/overview/tech_highlights.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/overview/tech_highlights.rst b/docs/source/overview/tech_highlights.rst index 1f4cd8b61..90e828de0 100644 --- a/docs/source/overview/tech_highlights.rst +++ b/docs/source/overview/tech_highlights.rst @@ -62,7 +62,7 @@ Supported Circuit Designs +-----------------+--------------+-----------+-----------------------------------------------------+ -* The user defined netlist could come from a standard cell. See :ref:`standard_cell_tutorial` for details. +* The user defined netlist could come from a standard cell. See :ref:`tutorial_standard_cell` for details. Supported FPGA Architectures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 96cb3081abf1aa90abd1e977476da88d0d779cdb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Jun 2021 09:51:16 -0600 Subject: [PATCH 337/352] Update fix_device_route_chan_width_example_script.openfpga --- .../fix_device_route_chan_width_example_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga index d31ffe36c..fe7679f65 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitsream.bit +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator --explicit_port_mapping write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --support_icarus_simulator From 0e01177cf08f015eb044cb9d28b772eca739ad14 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Jun 2021 11:01:45 -0600 Subject: [PATCH 338/352] [Script] Now openfpga flow script output detailed error message when task is not found --- openfpga_flow/scripts/run_fpga_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py index e8543a402..29a584505 100644 --- a/openfpga_flow/scripts/run_fpga_task.py +++ b/openfpga_flow/scripts/run_fpga_task.py @@ -174,7 +174,7 @@ def generate_each_task_actions(taskname): elif os.path.isdir(repo_tasks): curr_task_dir = repo_tasks else: - clean_up_and_exit("Task directory [%s] not found" % curr_task_dir) + clean_up_and_exit("Task directory not found" % taskname + " locally at [%s]" % local_tasks + " or in OpenFPGA task directory [%s]" % repo_tasks) os.chdir(curr_task_dir) From fce84e564d25c442a48c1657ac48bd7c970c5711 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Jun 2021 11:20:35 -0600 Subject: [PATCH 339/352] [Script] Patch on missing string to show in error message --- openfpga_flow/scripts/run_fpga_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py index 29a584505..5663cc55c 100644 --- a/openfpga_flow/scripts/run_fpga_task.py +++ b/openfpga_flow/scripts/run_fpga_task.py @@ -174,7 +174,7 @@ def generate_each_task_actions(taskname): elif os.path.isdir(repo_tasks): curr_task_dir = repo_tasks else: - clean_up_and_exit("Task directory not found" % taskname + " locally at [%s]" % local_tasks + " or in OpenFPGA task directory [%s]" % repo_tasks) + clean_up_and_exit("Task directory [%s] not found" % taskname + " locally at [%s]" % local_tasks + " or in OpenFPGA task directory [%s]" % repo_tasks) os.chdir(curr_task_dir) From fed975c52a782c604c443e3b2e21a295481a2c27 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Jun 2021 16:13:50 -0600 Subject: [PATCH 340/352] [Tool] Add postfix removal support in write_io_mapping command --- .../src/openfpga_reserved_words.h | 3 +++ openfpga/src/base/openfpga_bitstream.cpp | 9 ++++++++- .../src/fpga_bitstream/build_io_mapping_info.cpp | 16 ++++++++++++++-- .../src/fpga_bitstream/build_io_mapping_info.h | 3 ++- .../verilog_formal_random_top_testbench.cpp | 1 + .../src/fpga_verilog/verilog_testbench_utils.h | 3 --- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h index 2f9bae817..732247178 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h @@ -59,6 +59,9 @@ constexpr char* DEFAULT_LB_DIR_NAME = "lb/"; constexpr char* DEFAULT_RR_DIR_NAME = "routing/"; constexpr char* DEFAULT_SUBMODULE_DIR_NAME = "sub_module/"; +constexpr char* VPR_BENCHMARK_OUT_PORT_PREFIX = "out:"; +constexpr char* OPENFPGA_BENCHMARK_OUT_PORT_PREFIX = "out_"; + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index 78e0cbddd..b978b200d 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -10,6 +10,7 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" +#include "openfpga_reserved_words.h" /* Headers from fpgabitstream library */ #include "read_xml_arch_bitstream.h" @@ -153,6 +154,11 @@ int write_io_mapping(const OpenfpgaContext& openfpga_ctx, ModuleId top_module = openfpga_ctx.module_graph().find_module(top_module_name); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); + /* VPR added a prefix to the output ports, remove them here */ + std::vector prefix_to_remove; + prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX)); + prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX)); + IoMap io_map = build_fpga_io_mapping_info(openfpga_ctx.module_graph(), top_module, g_vpr_ctx.atom(), @@ -160,7 +166,8 @@ int write_io_mapping(const OpenfpgaContext& openfpga_ctx, openfpga_ctx.io_location_map(), openfpga_ctx.vpr_netlist_annotation(), std::string(), - std::string()); + std::string(), + prefix_to_remove); status = write_io_mapping_to_xml_file(io_map, cmd_context.option_value(cmd, opt_file), diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp index 76fbda9a2..3eb10fe37 100644 --- a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp @@ -37,7 +37,8 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, const IoLocationMap& io_location_map, const VprNetlistAnnotation& netlist_annotation, const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix) { + const std::string& io_output_port_name_postfix, + const std::vector& output_port_prefix_to_remove) { IoMap io_map; /* Only mappable i/o ports can be considered */ @@ -129,7 +130,18 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, benchmark_io_port.set_width(1); } else { VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); - benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix)); + /* VPR may have added a prefix to the output ports, remove them here */ + std::string output_block_name = block_name; + for (const std::string& prefix_to_remove : output_port_prefix_to_remove) { + if (!prefix_to_remove.empty()) { + if (0 == output_block_name.find(prefix_to_remove)) { + output_block_name.erase(0, prefix_to_remove.length()); + break; + } + } + } + + benchmark_io_port.set_name(std::string(output_block_name + io_output_port_name_postfix)); benchmark_io_port.set_width(1); } diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.h b/openfpga/src/fpga_bitstream/build_io_mapping_info.h index 615fafdd8..01f4b1d61 100644 --- a/openfpga/src/fpga_bitstream/build_io_mapping_info.h +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.h @@ -26,7 +26,8 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, const IoLocationMap& io_location_map, const VprNetlistAnnotation& netlist_annotation, const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix); + const std::string& io_output_port_name_postfix, + const std::vector& output_port_prefix_to_remove); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index 710a0312d..ffc15437b 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -16,6 +16,7 @@ /* Headers from openfpgautil library */ #include "openfpga_port.h" #include "openfpga_digest.h" +#include "openfpga_reserved_words.h" #include "openfpga_atom_netlist_utils.h" #include "simulation_utils.h" diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index 807d25ae5..1f9567481 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -23,9 +23,6 @@ /* begin namespace openfpga */ namespace openfpga { -constexpr char* VPR_BENCHMARK_OUT_PORT_PREFIX = "out:"; -constexpr char* OPENFPGA_BENCHMARK_OUT_PORT_PREFIX = "out_"; - void print_verilog_testbench_fpga_instance(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, From cbbf601edc88a49fbfeae12ac04c69ccc89bec38 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Jun 2021 16:20:13 -0600 Subject: [PATCH 341/352] [Tool] Fix a compiler warning due to uninitialized data structure --- openfpga/src/fabric/build_top_module_connection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 3fde3ee9c..03b04cd03 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -747,6 +747,7 @@ int build_top_module_global_net_for_given_grid_module(ModuleManager& module_mana /* Find the port of the grid module according to the tile annotation */ int grid_pin_start_index = physical_tile->num_pins; t_physical_tile_port physical_tile_port; + physical_tile_port.num_pins = 0; for (const t_physical_tile_port& tile_port : physical_tile->ports) { if (std::string(tile_port.name) == tile_port_to_connect.get_name()) { BasicPort ref_tile_port(tile_port.name, tile_port.num_pins); From f9e66e1bae4e3b16c452e5bea20d1c793e9b94b1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 15:27:12 -0600 Subject: [PATCH 342/352] [Script] Support benchmarks with same top module names in openfpga flow script; Now each benchmark local run directory has a unique name; --- openfpga_flow/scripts/run_fpga_task.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py index 5663cc55c..7855a54fd 100644 --- a/openfpga_flow/scripts/run_fpga_task.py +++ b/openfpga_flow/scripts/run_fpga_task.py @@ -309,7 +309,7 @@ def generate_each_task_actions(taskname): for indx, arch in enumerate(archfile_list): for bench in benchmark_list: for lbl, param in bench["script_params"].items(): - flow_run_dir = get_flow_rundir(arch, bench["top_module"], lbl) + flow_run_dir = get_flow_rundir(arch, benchmark_list.index(bench), bench["top_module"], lbl) command = create_run_command( curr_job_dir=flow_run_dir, archfile=arch, @@ -330,11 +330,12 @@ def generate_each_task_actions(taskname): logger.info('Created total %d jobs' % len(flow_run_cmd_list)) return flow_run_cmd_list - -def get_flow_rundir(arch, top_module, flow_params=None): +# Make the directory name unique by including the benchmark index in the list. +# This is because benchmarks may share the same top module names +def get_flow_rundir(arch, bench_index, top_module, flow_params=None): path = [ os.path.basename(arch).replace(".xml", ""), - top_module, + "bench" + str(bench_index) + "_" + top_module, flow_params if flow_params else "common" ] return os.path.abspath(os.path.join(*path)) From 07dcf3ad27bd7de8b8303f693fb37dd394439548 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 16:48:35 -0600 Subject: [PATCH 343/352] [HDL] Add more micro benchmarks for counter, and-gate and mac unit --- .../benchmarks/micro_benchmark/and4/and4.v | 22 ++++++++++++++++ .../counter_128bit_async_reset/counter.v | 25 +++++++++++++++++++ .../counter_128bit_async_reset/counter_tb.v | 25 +++++++++++++++++++ .../counter_128bit_async_resetb/counter.v | 25 +++++++++++++++++++ .../counter_128bit_async_resetb/counter_tb.v | 25 +++++++++++++++++++ .../micro_benchmark/mac/mac_18/mac_18.v | 22 ++++++++++++++++ .../micro_benchmark/mac/mac_20/mac_20.v | 22 ++++++++++++++++ .../micro_benchmark/mac/mac_36/mac_36.v | 22 ++++++++++++++++ .../micro_benchmark/mac/mac_8_9/mac_8_9.v | 25 +++++++++++++++++++ .../micro_benchmark/mac/mac_9/mac_9.v | 22 ++++++++++++++++ 10 files changed, 235 insertions(+) create mode 100644 openfpga_flow/benchmarks/micro_benchmark/and4/and4.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter_tb.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter_tb.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/mac/mac_18/mac_18.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/mac/mac_20/mac_20.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/mac/mac_36/mac_36.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/mac/mac_8_9/mac_8_9.v create mode 100644 openfpga_flow/benchmarks/micro_benchmark/mac/mac_9/mac_9.v diff --git a/openfpga_flow/benchmarks/micro_benchmark/and4/and4.v b/openfpga_flow/benchmarks/micro_benchmark/and4/and4.v new file mode 100644 index 000000000..4b71607f6 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/and4/and4.v @@ -0,0 +1,22 @@ +///////////////////////////////////////// +// Functionality: 4-input AND +// Author: Xifan Tang +//////////////////////////////////////// +`timescale 1ns / 1ps + +module and4( + a, + b, + c, + d, + e); + +input wire a; +input wire b; +input wire c; +input wire d; +output wire e; + +assign e = a & b & c & d; + +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter.v b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter.v new file mode 100644 index 000000000..4a3542eec --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter.v @@ -0,0 +1,25 @@ +/////////////////////////////////////////// +// Functionality: Counter with asynchronous reset +// Author: Xifan Tang +//////////////////////////////////////// + +module counter ( + clk, + reset, + result +); + + input clk; + input reset; + output [127:0] result; + + reg [127:0] result; + + always @(posedge clk or posedge reset) + begin + if (reset) + result = 0; + else + result = result + 1; + end +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter_tb.v b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter_tb.v new file mode 100644 index 000000000..4d11e9e0b --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter_tb.v @@ -0,0 +1,25 @@ +module counter_tb; + + reg clk, reset; + wire [127:0] result; + + counter DUT( + .clk(clk), + .reset(reset), + .result(result) + ); + + initial begin + #0 reset = 1'b1; clk = 1'b0; + #100 reset = 1'b0; + end + + always begin + #10 clk = ~clk; + end + + initial begin + #5000 $stop; + end + +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v new file mode 100644 index 000000000..d5e8ce2a8 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v @@ -0,0 +1,25 @@ +/////////////////////////////////////////// +// Functionality: Counter with asynchronous reset +// Author: Xifan Tang +//////////////////////////////////////// + +module counter ( + clk, + resetb, + result +); + + input clk; + input reset; + output [127:0] result; + + reg [127:0] result; + + always @(posedge clk or negedge resetb) + begin + if (~resetb) + result = 0; + else + result = result + 1; + end +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter_tb.v b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter_tb.v new file mode 100644 index 000000000..c96557b4e --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter_tb.v @@ -0,0 +1,25 @@ +module counter_tb; + + reg clk, resetb; + wire [127:0] result; + + counter DUT( + .clk(clk), + .resetb(resetb), + .result(result) + ); + + initial begin + #0 reset = 1'b0; clk = 1'b0; + #100 reset = 1'b1; + end + + always begin + #10 clk = ~clk; + end + + initial begin + #5000 $stop; + end + +endmodule diff --git a/openfpga_flow/benchmarks/micro_benchmark/mac/mac_18/mac_18.v b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_18/mac_18.v new file mode 100644 index 000000000..74a935e8d --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_18/mac_18.v @@ -0,0 +1,22 @@ +//------------------------------------------------------- +// Functionality: A 18-bit multiply-acculumate circuit +// Author: Xifan Tang +//------------------------------------------------------- + +module mac_18(a, b, c, out); +parameter DATA_WIDTH = 18; /* declare a parameter. default required */ +input [DATA_WIDTH - 1 : 0] a, b, c; +output [DATA_WIDTH - 1 : 0] out; + +assign out = a * b + c; + +endmodule + + + + + + + + + diff --git a/openfpga_flow/benchmarks/micro_benchmark/mac/mac_20/mac_20.v b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_20/mac_20.v new file mode 100644 index 000000000..f7be3eff9 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_20/mac_20.v @@ -0,0 +1,22 @@ +//------------------------------------------------------- +// Functionality: A 20-bit multiply-acculumate circuit +// Author: Xifan Tang +//------------------------------------------------------- + +module mac_20(a, b, c, out); +parameter DATA_WIDTH = 20; /* declare a parameter. default required */ +input [DATA_WIDTH - 1 : 0] a, b, c; +output [DATA_WIDTH - 1 : 0] out; + +assign out = a * b + c; + +endmodule + + + + + + + + + diff --git a/openfpga_flow/benchmarks/micro_benchmark/mac/mac_36/mac_36.v b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_36/mac_36.v new file mode 100644 index 000000000..669bc4747 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_36/mac_36.v @@ -0,0 +1,22 @@ +//------------------------------------------------------- +// Functionality: A 36-bit multiply-acculumate circuit +// Author: Xifan Tang +//------------------------------------------------------- + +module mac_36(a, b, c, out); +parameter DATA_WIDTH = 4; /* declare a parameter. default required */ +input [DATA_WIDTH - 1 : 0] a, b, c; +output [DATA_WIDTH - 1 : 0] out; + +assign out = a * b + c; + +endmodule + + + + + + + + + diff --git a/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8_9/mac_8_9.v b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8_9/mac_8_9.v new file mode 100644 index 000000000..05df02fac --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8_9/mac_8_9.v @@ -0,0 +1,25 @@ +//------------------------------------------------------- +// Functionality: +// - A 8-bit multiply-acculumate circuit +// - A 9-bit multiply-acculumate circuit +// Author: Xifan Tang +//------------------------------------------------------- + +module mac_8_9(a, b, c, out); +parameter DATA_WIDTH = 18; /* declare a parameter. default required */ +input [DATA_WIDTH - 1 : 0] a, b, c; +output [DATA_WIDTH - 1 : 0] out; + +assign out[8:0] = a[8:0] * b[8:0] + c[8:0]; +assign out[17:9] = a[17:9] * b[17:9] + c[17:9]; + +endmodule + + + + + + + + + diff --git a/openfpga_flow/benchmarks/micro_benchmark/mac/mac_9/mac_9.v b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_9/mac_9.v new file mode 100644 index 000000000..664df33f4 --- /dev/null +++ b/openfpga_flow/benchmarks/micro_benchmark/mac/mac_9/mac_9.v @@ -0,0 +1,22 @@ +//------------------------------------------------------- +// Functionality: A 9-bit multiply-acculumate circuit +// Author: Xifan Tang +//------------------------------------------------------- + +module mac_9(a, b, c, out); +parameter DATA_WIDTH = 9; /* declare a parameter. default required */ +input [DATA_WIDTH - 1 : 0] a, b, c; +output [DATA_WIDTH - 1 : 0] out; + +assign out = a * b + c; + +endmodule + + + + + + + + + From 9c24a739bebafa73a6decd967bfc8fc3d8af127e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 17:40:53 -0600 Subject: [PATCH 344/352] [Test] Added a MAC benchmark sweeping test --- .../mac_units/config/task.conf | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 openfpga_flow/tasks/benchmark_sweep/mac_units/config/task.conf diff --git a/openfpga_flow/tasks/benchmark_sweep/mac_units/config/task.conf b/openfpga_flow/tasks/benchmark_sweep/mac_units/config/task.conf new file mode 100644 index 000000000..0fddaa91a --- /dev/null +++ b/openfpga_flow/tasks/benchmark_sweep/mac_units/config/task.conf @@ -0,0 +1,67 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +# VPR parameters +# Use a fixed routing channel width to save runtime +vpr_route_chan_width=300 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_2/mac_2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_6/mac_6.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v +bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8_9/mac_8_9.v +bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_9/mac_9.v +bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_12/mac_12.v +bench7=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_16/mac_16.v +bench8=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_18/mac_18.v +bench9=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_20/mac_20.v +bench10=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_32/mac_32.v +bench11=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_36/mac_36.v + +[SYNTHESIS_PARAM] +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys +bench0_top = mac_2 +bench1_top = mac_4 +bench2_top = mac_6 +bench3_top = mac_8 +bench4_top = mac_8_9 +bench5_top = mac_9 +bench6_top = mac_12 +bench7_top = mac_16 +bench8_top = mac_18 +bench9_top = mac_20 +bench10_top = mac_32 +bench11_top = mac_36 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +#end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From 760570d8835fad8457966419398343db56fb9fca Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 18:13:18 -0600 Subject: [PATCH 345/352] [Test] Update counter test case for cover most counter HDL design --- .../benchmark_sweep/counter/config/task.conf | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf b/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf index 9d5a92747..7cedf7d27 100644 --- a/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf +++ b/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf @@ -12,26 +12,36 @@ power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml power_analysis = true spice_output=false verilog_output=true -timeout_each_job = 20*60 -fpga_flow=vpr_blif +timeout_each_job = 5*60 +fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/implicit_verilog_example_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_N10_40nm_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_pin_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/benchmark_sweep/counter/config/pin_constraints.xml +# Yosys script parameters +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v +yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v [ARCHITECTURES] -arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_N10_40nm.xml +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter/counter_post_yosys.blif +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter/counter.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_async_reset/counter.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_reset/counter.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v [SYNTHESIS_PARAM] +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + bench0_top = counter -bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter/counter_pre_vpr.act -bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter/counter_output_verilog.v -bench0_chan_width = 300 +bench1_top = counter +bench2_top = counter +bench3_top = counter [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] -end_flow_with_test= +#end_flow_with_test= #vpr_fpga_verilog_formal_verification_top_netlist= From 0b2d6eb14787cda9a92a2426ddec709ab6f8558f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 18:35:41 -0600 Subject: [PATCH 346/352] [Test] Add micro benchmark to a dedicated regression test --- .../micro_benchmark_reg_test.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh diff --git a/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh b/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh new file mode 100755 index 000000000..dc8e9ddc2 --- /dev/null +++ b/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +source openfpga.sh +PYTHON_EXEC=python3.8 +############################################### +# OpenFPGA Shell with VPR8 +############################################## +echo -e "Micro benchmark regression tests"; +# TODO: enable this when flow-run script support same top module name in one task configuration file +#run-task benchmark_sweep/counter --debug --show_thread_logs +run-task benchmark_sweep/mac_units --debug --show_thread_logs From 260b14c3d4bcbcb50b60fa0f4b925d9a4586b527 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 21 Jun 2021 18:37:42 -0600 Subject: [PATCH 347/352] [CI] Add the micro benchmark regression test to CI --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 753b4c77f..77ccb1527 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -210,6 +210,7 @@ jobs: - name: fpga_bitstream_reg_test - name: fpga_sdc_reg_test - name: fpga_spice_reg_test + - name: micro_benchmark_reg_test - name: quicklogic_reg_test - name: vtr_benchmark_reg_test - name: iwls_benchmark_reg_test @@ -257,6 +258,7 @@ jobs: - name: fpga_bitstream_reg_test - name: fpga_sdc_reg_test - name: fpga_spice_reg_test + - name: micro_benchmark_reg_test - name: quicklogic_reg_test - name: vtr_benchmark_reg_test - name: iwls_benchmark_reg_test From fd580bb36f8b7ad5d326a86f269b14f5560d9c92 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 22 Jun 2021 11:45:23 -0600 Subject: [PATCH 348/352] [Script] Update script to keep back compatibility: local run directory is different only for those benchmarks sharing the same top module name --- openfpga_flow/scripts/run_fpga_task.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py index 7855a54fd..0cb6612e1 100644 --- a/openfpga_flow/scripts/run_fpga_task.py +++ b/openfpga_flow/scripts/run_fpga_task.py @@ -302,6 +302,13 @@ def generate_each_task_actions(taskname): benchmark_list.append(CurrBenchPara) + # Count the number of duplicated top module name among benchmark + # This is required as flow run directory names for these benchmarks are different than others + # which are uniquified + benchmark_top_module_count = [] + for bench in benchmark_list: + benchmark_top_module_count.append(bench["top_module"]) + # Create OpenFPGA flow run commnad for each combination of # architecture, benchmark and parameters # Create run_job object [arch, bench, run_dir, commnad] @@ -309,7 +316,11 @@ def generate_each_task_actions(taskname): for indx, arch in enumerate(archfile_list): for bench in benchmark_list: for lbl, param in bench["script_params"].items(): - flow_run_dir = get_flow_rundir(arch, benchmark_list.index(bench), bench["top_module"], lbl) + if (benchmark_top_module_count.count(bench["top_module"]) > 1): + flow_run_dir = get_flow_rundir(arch, "bench" + str(benchmark_list.index(bench)) + "_" + bench["top_module"], lbl) + else: + flow_run_dir = get_flow_rundir(arch, bench["top_module"], lbl) + command = create_run_command( curr_job_dir=flow_run_dir, archfile=arch, @@ -332,10 +343,10 @@ def generate_each_task_actions(taskname): # Make the directory name unique by including the benchmark index in the list. # This is because benchmarks may share the same top module names -def get_flow_rundir(arch, bench_index, top_module, flow_params=None): +def get_flow_rundir(arch, top_module, flow_params=None): path = [ os.path.basename(arch).replace(".xml", ""), - "bench" + str(bench_index) + "_" + top_module, + top_module, flow_params if flow_params else "common" ] return os.path.abspath(os.path.join(*path)) From 0a0d10b36d220a977051ad9ee243b61f721ee4a7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 22 Jun 2021 16:18:46 -0600 Subject: [PATCH 349/352] [HDL] Bug fix in Verilog syntax --- .../micro_benchmark/counter_128bit_async_resetb/counter.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v index d5e8ce2a8..628ec4c08 100644 --- a/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v +++ b/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v @@ -10,7 +10,7 @@ module counter ( ); input clk; - input reset; + input resetb; output [127:0] result; reg [127:0] result; From f06017581c2e7d72b210327c4da9b22cf627417e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 22 Jun 2021 16:33:50 -0600 Subject: [PATCH 350/352] [Test] Bug fix in counter micro benchmark tests --- .../benchmark_sweep/counter/config/task.conf | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf b/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf index 7cedf7d27..eb0079516 100644 --- a/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf +++ b/openfpga_flow/tasks/benchmark_sweep/counter/config/task.conf @@ -9,23 +9,29 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 5*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/iwls_benchmark_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml -openfpga_pin_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/benchmark_sweep/counter/config/pin_constraints.xml # Yosys script parameters -yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v -yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v +yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v +yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +yosys_dsp_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +yosys_dsp_map_parameters=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +# VPR parameters +# # Use a fixed routing channel width to save runtime +vpr_route_chan_width=50 [ARCHITECTURES] -arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml [BENCHMARKS] bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter/counter.v @@ -34,8 +40,8 @@ bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_12 bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counter_128bit_async_resetb/counter.v [SYNTHESIS_PARAM] -bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys -bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_dff_flow.ys +#bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys bench0_top = counter bench1_top = counter From e34fbf8ecf8f7769fd650ab48e2200997a1a60e5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 22 Jun 2021 16:36:04 -0600 Subject: [PATCH 351/352] [Test] Deploy MCNC big20 to the micro benchmark regression test --- .../regression_test_scripts/fpga_verilog_reg_test.sh | 6 ------ .../regression_test_scripts/micro_benchmark_reg_test.sh | 9 +++++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 70137dd77..9c51ef6ea 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -136,9 +136,3 @@ run-task fpga_verilog/fully_connected_output_crossbar --debug --show_thread_logs echo -e "Testing through channels in tileable routing"; run-task fpga_verilog/thru_channel/thru_narrow_tile --debug --show_thread_logs run-task fpga_verilog/thru_channel/thru_wide_tile --debug --show_thread_logs - -# Verify MCNC big20 benchmark suite with ModelSim -# Please make sure you have ModelSim installed in the environment -# Otherwise, it will fail -#run-task fpga_verilog/mcnc_big20 --debug --show_thread_logs --maxthreads 20 -#python3 openfpga_flow/scripts/run_modelsim.py mcnc_big20 --run_sim diff --git a/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh b/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh index dc8e9ddc2..28b24aef3 100755 --- a/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/micro_benchmark_reg_test.sh @@ -7,6 +7,11 @@ PYTHON_EXEC=python3.8 # OpenFPGA Shell with VPR8 ############################################## echo -e "Micro benchmark regression tests"; -# TODO: enable this when flow-run script support same top module name in one task configuration file -#run-task benchmark_sweep/counter --debug --show_thread_logs +run-task benchmark_sweep/counter --debug --show_thread_logs run-task benchmark_sweep/mac_units --debug --show_thread_logs + +# Verify MCNC big20 benchmark suite with ModelSim +# Please make sure you have ModelSim installed in the environment +# Otherwise, it will fail +run-task benchmark_sweep/mcnc_big20 --debug --show_thread_logs +#python3 openfpga_flow/scripts/run_modelsim.py mcnc_big20 --run_sim From b2c30e3103a695749eb56fdce37f9d227ae2cf6c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 22 Jun 2021 16:40:24 -0600 Subject: [PATCH 352/352] [Test] Bug fix in mcnc openfpga shell script --- .../mcnc_example_script.openfpga | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga index 56b5c9caf..7f2984f96 100644 --- a/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/mcnc_example_script.openfpga @@ -37,7 +37,7 @@ repack #--verbose # Build the bitstream # - Output the fabric-independent bitstream to a file -build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml +build_architecture_bitstream --verbose # Build fabric-dependent bitstream build_fabric_bitstream --verbose @@ -46,9 +46,7 @@ build_fabric_bitstream --verbose # - Enable the use of explicit port mapping in Verilog netlist write_fabric_verilog --file ./SRC \ --explicit_port_mapping \ - --include_timing \ - --include_signal_init -# --support_icarus_simulator + --include_timing # Write the Verilog testbench for FPGA fabric # - We suggest the use of same output directory as fabric Verilog netlists @@ -59,16 +57,6 @@ write_fabric_verilog --file ./SRC \ write_preconfigured_fabric_wrapper --file ./SRC --support_icarus_simulator write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --support_icarus_simulator -# Write the SDC files for PnR backend -# - Turn on every options here -write_pnr_sdc --file ./SDC - -# Write SDC to disable timing for configure ports -write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc - -# Write the SDC to run timing analysis for a mapped FPGA fabric -write_analysis_sdc --file ./SDC_analysis - # Finish and exit OpenFPGA exit

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 j6~jZCOrkEfVPS({5%EAf{gH%ddl-7&W11k%9k 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�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

|L$A1=F{_Ur$GW2nHZ8jvq|KhgKA(KDq->}sG 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 C8Q-UaB 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 literal 0 HcmV?d00001 From eea73ca2bf53e4358b05ecddc6fc26e0fd3d5ea5 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:10:46 -0600 Subject: [PATCH 003/352] Add user_defined_templates.rst file --- .../user_defined_temp_tutorial.rst | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst new file mode 100644 index 000000000..b8d635f94 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -0,0 +1,28 @@ +================================================================ +Integrating Custom Verilog Modules with user_defined_templates.v +================================================================ +1. Introduction +=============== +**In this tutorial, we will** +- Provide motivation for generating the user_defined_templates.v verilog file +- Go through a generated user_defined_templates.v file to demonstrate how to use it +For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA +To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. +.. image:: modified_arch_file.png +From the OpenFPGA root directory run the command +``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` +Running this command should fail and produce output similar to this +.. image:: Error_log.png +This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. +This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: +``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` +The above line provides a path for now to generate the user_defined_templates.v file. +Now we can return to the root directory and run this command again: +``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` +The user_defined_templates.v file can be found within the sub_module directory located at: +``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` +The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. +To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined +.. image:: modified_user_defined_templates_file.png +We can now link this definition into the architecture file and run the task script again. +There should be no errors if this is done correctly. From 4e363660e7c7d1747e1e901a47252cc260f698de Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:14:51 -0600 Subject: [PATCH 004/352] Update to correct syntax for images --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index b8d635f94..1dcb8738c 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -8,11 +8,11 @@ Integrating Custom Verilog Modules with user_defined_templates.v - Go through a generated user_defined_templates.v file to demonstrate how to use it For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. -.. image:: modified_arch_file.png +.. figure:: ./figures/modified_arch_file.png From the OpenFPGA root directory run the command ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` Running this command should fail and produce output similar to this -.. image:: Error_log.png +.. figure:: ./figures/Error_log.png This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: ``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` @@ -23,6 +23,6 @@ The user_defined_templates.v file can be found within the sub_module directory l ``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined -.. image:: modified_user_defined_templates_file.png +.. figure:: ./figures/modified_user_defined_templates_file.png We can now link this definition into the architecture file and run the task script again. There should be no errors if this is done correctly. From 05ec5186a2521bea2748f98afb0c8a7d61e2afd2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:18:21 -0600 Subject: [PATCH 005/352] Update to see if .. image:: works for images --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 1dcb8738c..3805d70c3 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -8,11 +8,11 @@ Integrating Custom Verilog Modules with user_defined_templates.v - Go through a generated user_defined_templates.v file to demonstrate how to use it For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. -.. figure:: ./figures/modified_arch_file.png +.. image:: ./figures/modified_arch_file.png From the OpenFPGA root directory run the command ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` Running this command should fail and produce output similar to this -.. figure:: ./figures/Error_log.png +.. image:: ./figures/Error_log.png This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: ``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` @@ -23,6 +23,6 @@ The user_defined_templates.v file can be found within the sub_module directory l ``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined -.. figure:: ./figures/modified_user_defined_templates_file.png +.. image:: ./figures/modified_user_defined_templates_file.png We can now link this definition into the architecture file and run the task script again. There should be no errors if this is done correctly. From e90bcdc4d53b1bf86d03cce37c2c631bb6ae22d2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:21:45 -0600 Subject: [PATCH 006/352] Update to correctly include figure syntax --- .../arch_modeling/user_defined_temp_tutorial.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 3805d70c3..8fad8bd4e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -8,11 +8,13 @@ Integrating Custom Verilog Modules with user_defined_templates.v - Go through a generated user_defined_templates.v file to demonstrate how to use it For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. -.. image:: ./figures/modified_arch_file.png +.. figure:: ./figures/modified_arch_file.png + :scale: 50 % From the OpenFPGA root directory run the command ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` Running this command should fail and produce output similar to this -.. image:: ./figures/Error_log.png +.. figure:: ./figures/Error_log.png + :scale: 50 % This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: ``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` @@ -23,6 +25,7 @@ The user_defined_templates.v file can be found within the sub_module directory l ``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined -.. image:: ./figures/modified_user_defined_templates_file.png +.. figure:: ./figures/modified_user_defined_templates_file.png + :scale: 50 % We can now link this definition into the architecture file and run the task script again. There should be no errors if this is done correctly. From a6dfba45001ee7a4c0f8be1ca117c4fff049c97d Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:29:25 -0600 Subject: [PATCH 007/352] Update to try and display tutorial images --- .../arch_modeling/user_defined_temp_tutorial.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 8fad8bd4e..bcc96b4bc 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -8,13 +8,17 @@ Integrating Custom Verilog Modules with user_defined_templates.v - Go through a generated user_defined_templates.v file to demonstrate how to use it For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. + .. figure:: ./figures/modified_arch_file.png - :scale: 50 % + :scale: 50% + From the OpenFPGA root directory run the command ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` Running this command should fail and produce output similar to this + .. figure:: ./figures/Error_log.png - :scale: 50 % + :scale: 50% + This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: ``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` @@ -25,7 +29,9 @@ The user_defined_templates.v file can be found within the sub_module directory l ``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined + .. figure:: ./figures/modified_user_defined_templates_file.png - :scale: 50 % + :scale: 50% + We can now link this definition into the architecture file and run the task script again. There should be no errors if this is done correctly. From 1185f7b8bf8685e91b325d26687a2373d9036733 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 20 Mar 2021 17:05:30 -0600 Subject: [PATCH 008/352] [Script] Add a template yosys script to enable DSP mapping --- .../misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys diff --git a/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys new file mode 100644 index 000000000..ebe101ed2 --- /dev/null +++ b/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_dsp_flow.ys @@ -0,0 +1,102 @@ +# Yosys synthesis script for ${TOP_MODULE} + +######################### +# Parse input files +######################### +# Read verilog files +${READ_VERILOG_FILE} +# Read technology library +read_verilog -lib -specify ${YOSYS_CELL_SIM_VERILOG} + +######################### +# Prepare for synthesis +######################### +# Identify top module from hierarchy +hierarchy -check -top ${TOP_MODULE} +# - Convert process blocks to AST +proc +# Flatten all the gates/primitives +flatten +# Identify tri-state buffers from 'z' signal in AST +# with follow-up optimizations to clean up AST +tribuf -logic +opt_expr +opt_clean +# demote inout ports to input or output port +# with follow-up optimizations to clean up AST +deminout +opt + +opt_expr +opt_clean +check +opt +wreduce -keepdc +peepopt +pmuxtree +opt_clean + +######################## +# Map multipliers +# Inspired from synth_xilinx.cc +######################### +techmap -map +/mul2dsp.v -map ${YOSYS_DSP_MAP_VERILOG} ${YOSYS_DSP_MAP_PARAMETERS} +select a:mul2dsp +setattr -unset mul2dsp +opt_expr -fine +wreduce +select -clear +chtype -set $mul t:$__soft_mul# Extract arithmetic functions + +######################### +# Run coarse synthesis +######################### +# Run a tech map with default library +techmap +alumacc +share +opt +fsm +# Run a quick follow-up optimization to sweep out unused nets/signals +opt -fast +# Optimize any memory cells by merging share-able ports and collecting all the ports belonging to memorcy cells +memory -nomap +opt_clean + +######################### +# Map logics to BRAMs +######################### +memory_bram -rules ${YOSYS_BRAM_MAP_RULES} +techmap -map ${YOSYS_BRAM_MAP_VERILOG} +opt -fast -mux_undef -undriven -fine +memory_map +opt -undriven -fine + +######################### +# Map flip-flops +######################### +techmap -map +/adff2dff.v +opt_expr -mux_undef +simplemap +opt_expr +opt_merge +opt_rmdff +opt_clean +opt + +######################### +# Map LUTs +######################### +abc -lut ${LUT_SIZE} + +######################### +# Check and show statisitics +######################### +hierarchy -check +stat + +######################### +# Output netlists +######################### +opt_clean -purge +write_blif ${OUTPUT_BLIF} From 911979a731fe810c0e61d16db2e76460d4c65bac Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 20 Mar 2021 18:04:59 -0600 Subject: [PATCH 009/352] [Arch] Update heterogenous architecture for vtr benchmark by adding mult36 --- ...der_chain_dpram8K_dsp36_40nm_openfpga.xml} | 14 ++++ ...leable_adder_chain_dpram8K_dsp36_40nm.xml} | 80 +++++++++++++++++++ ...egister_scan_chain_mem16K_depop50_12nm.xml | 11 ++- 3 files changed, 104 insertions(+), 1 deletion(-) rename openfpga_flow/openfpga_arch/{k6_frac_N10_adder_chain_dpram8K_40nm_openfpga.xml => k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml} (93%) rename openfpga_flow/vpr_arch/{k6_frac_N10_tileable_adder_chain_dpram8K_40nm.xml => k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml} (91%) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml similarity index 93% rename from openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_40nm_openfpga.xml rename to openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml index 37beb67bf..ed8f0134c 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_40nm_openfpga.xml @@ -206,6 +206,16 @@ + + + + + + + + + + @@ -265,6 +275,10 @@ + + + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml similarity index 91% rename from openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_40nm.xml rename to openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml index d697a1e8d..a34b29c22 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm.xml @@ -138,6 +138,15 @@ + + + + + + + + + @@ -196,6 +205,23 @@ memory.waddr[9:5] memory.raddr[9:5] memory.data_in[7:4] memory.ren memory.data_out[7:4] + + + + + + + + + + + + mult_36.b[0:9] mult_36.b[10:35] mult_36.out[36:71] + + mult_36.a[0:9] mult_36.a[10:35] mult_36.out[0:35] + + + @@ -208,6 +234,8 @@ + + @@ -686,6 +714,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_mem16K_depop50_12nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_mem16K_depop50_12nm.xml index baada7911..b6dad0a8f 100755 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_mem16K_depop50_12nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_mem16K_depop50_12nm.xml @@ -193,7 +193,16 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml new file mode 100644 index 000000000..fea61541c --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml @@ -0,0 +1,906 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io_top.outpad io_top.inpad + + + + + + + + + + + + io_right.outpad io_right.inpad + + + + + + + + + + + + io_bottom.outpad io_bottom.inpad + + + + + + + + + + + + io_left.outpad io_left.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clb.clk clb.reset + clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I0 clb.I0i clb.I1 clb.I1i clb.I2 clb.I2i clb.I3 clb.I3i + clb.O[15:8] clb.I4 clb.I4i clb.I5 clb.I5i clb.I6 clb.I6i clb.I7 clb.I7i + clb.reg_out clb.sc_out clb.cout + + + + + + + + + + + + + + + + mult_8.a[0:5] mult_8.b[0:5] mult_8.out[0:10] + mult_8.a[6:7] mult_8.b[6:7] mult_8.out[11:15] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 145a80de434ec3c4362290a456f85ffcef89fa9c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Mar 2021 15:35:34 -0600 Subject: [PATCH 042/352] [Script] Add an openfpga shell script for heterogeneous fpga verification --- ...terogeneous_device_example_script.openfpga | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga new file mode 100644 index 000000000..10ed5f17a --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 108c84a022babebc649fc2d4d4c49b740d4074f3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Mar 2021 15:36:09 -0600 Subject: [PATCH 043/352] [HDL] Add HDL for 8-bit single-mode multiplier --- .../openfpga_cell_library/verilog/mult_8x8.v | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 openfpga_flow/openfpga_cell_library/verilog/mult_8x8.v diff --git a/openfpga_flow/openfpga_cell_library/verilog/mult_8x8.v b/openfpga_flow/openfpga_cell_library/verilog/mult_8x8.v new file mode 100644 index 000000000..a8649488b --- /dev/null +++ b/openfpga_flow/openfpga_cell_library/verilog/mult_8x8.v @@ -0,0 +1,16 @@ +//----------------------------------------------------- +// Design Name : mult_8x8 +// File Name : mult_8x8.v +// Function : A 8-bit multiplier +// Coder : Xifan Tang +//----------------------------------------------------- + +module mult_8x8 ( + input [0:7] A, + input [0:7] B, + output [0:15] Y +); + + assign Y = A * B; + +endmodule From d82ffe0cbf36eec45e697df93cfa765fdea0c904 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Mar 2021 15:36:28 -0600 Subject: [PATCH 044/352] [Test] Deploy MAC_8 benchmark to regression test --- openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 450bc262c..0033ad8ac 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -44,6 +44,9 @@ run-task fpga_verilog/bram/dpram16k --debug --show_thread_logs echo -e "Testing Verilog generation with 16k block RAMs spanning two columns "; run-task fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs +echo -e "Testing Verilog generation with heterogeneous fabric using 8-bit single-mode multipliers "; +run-task fpga_verilog/dsp/single_mode_mult_8x8 --debug --show_thread_logs + echo -e "Testing Verilog generation with different I/O capacities on each side of an FPGA "; run-task fpga_verilog/io/multi_io_capacity --debug --show_thread_logs From b00b4f0f5fd7382dd838ba958baa3bc223533d44 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Mar 2021 15:44:53 -0600 Subject: [PATCH 045/352] [HDL] Patch the yosys techlib for the heterogeneous FPGA by using little endian --- ..._adder_chain_dpram8K_dsp36_40nm_bram_map.v | 8 +++--- ..._adder_chain_dpram8K_dsp36_40nm_cell_sim.v | 26 +++++++++---------- ...e_adder_chain_dpram8K_dsp36_40nm_dsp_map.v | 6 ++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v index fdc8bef43..804077258 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v @@ -1,9 +1,9 @@ module $__MY_DPRAM_1024x8 ( - output [7:0] B1DATA, + output [0:7] B1DATA, input CLK1, - input [9:0] B1ADDR, - input [9:0] A1ADDR, - input [7:0] A1DATA, + input [0:9] B1ADDR, + input [0:9] A1ADDR, + input [0:7] A1DATA, input A1EN, input B1EN ); diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v index 5e99dc55f..bc8f1206e 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_cell_sim.v @@ -5,15 +5,15 @@ module dpram_1024x8_core ( input wclk, input wen, - input [9:0] waddr, - input [7:0] data_in, + input [0:9] waddr, + input [0:7] data_in, input rclk, input ren, - input [9:0] raddr, - output [7:0] data_out ); + input [0:9] raddr, + output [0:7] data_out ); - reg [7:0] ram[1023:0]; - reg [7:0] internal; + reg [0:7] ram[0:1023]; + reg [0:7] internal; assign data_out = internal; @@ -40,10 +40,10 @@ module dpram_1024x8 ( input clk, input wen, input ren, - input [9:0] waddr, - input [9:0] raddr, - input [7:0] data_in, - output [7:0] data_out ); + input [0:9] waddr, + input [0:9] raddr, + input [0:7] data_in, + output [0:7] data_out ); dpram_1024x8_core memory_0 ( .wclk (clk), @@ -61,9 +61,9 @@ endmodule // 36-bit multiplier //----------------------------- module mult_36( - input [35:0] A, - input [35:0] B, - output [71:0] Y + input [0:35] A, + input [0:35] B, + output [0:71] Y ); assign Y = A * B; diff --git a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v index 4620af74d..977afdb13 100644 --- a/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v @@ -1,7 +1,7 @@ module mult_36x36 ( - input [35:0] A, - input [35:0] B, - output [71:0] Y + input [0:35] A, + input [0:35] B, + output [0:71] Y ); parameter A_SIGNED = 0; parameter B_SIGNED = 0; From 4d0e06c332565915d376349df6a5996734d828a2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:34:32 -0600 Subject: [PATCH 046/352] Update user_defined_temp_tutorial Add more sections, robust instructions, and a link to documentation --- .../user_defined_temp_tutorial.rst | 85 ++++++++++++++----- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index bcc96b4bc..84a0e2834 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -1,37 +1,78 @@ -================================================================ Integrating Custom Verilog Modules with user_defined_templates.v ================================================================ -1. Introduction -=============== +Introduction and Setup +~~~~~~~~~~~~~~~~~~~~~~ **In this tutorial, we will** -- Provide motivation for generating the user_defined_templates.v verilog file -- Go through a generated user_defined_templates.v file to demonstrate how to use it -For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA -To follow along, remove the path for the verilog_netlist in the file k6_frac_N10_adder_chain_40nm_openfpga.xml at line 187. + - Provide motivation for generating the user_defined_templates.v verilog file + - Go through a generated user_defined_templates.v file to demonstrate how to use it +Through this example, we will motivate and show how to use the user_defined_templates.v file. + +For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA. +To follow along, go to the root directory of OpenFPGA and enter: + +``vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml`` + +Go to line 187 and remove the path for the verilog_netlist. The modified file should look like :numref:`fig_modified_arch_file`. + +.. _fig_modified_arch_file: .. figure:: ./figures/modified_arch_file.png :scale: 50% - + The Modified k6_frac_N10_adder_chain_40nm_openfpga.xml File +Motivation +~~~~~~~~~~ From the OpenFPGA root directory run the command + ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` -Running this command should fail and produce output similar to this + +Running this command should fail and produce output similar to :numref:`fig_Error_log`. + +.. _fig_Error_log: .. figure:: ./figures/Error_log.png :scale: 50% - + Errors Created by k6_frac_N10_adder_chain_40nm_openfpga.xml File Modification This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. -This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist: -``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` -The above line provides a path for now to generate the user_defined_templates.v file. -Now we can return to the root directory and run this command again: -``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` -The user_defined_templates.v file can be found within the sub_module directory located at: -``./openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module`` -The file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. This file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. -To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should look similar to this once ADDF is defined +Fixing the Error +~~~~~~~~~~~~~~~~ +This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist location: + +``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` + +The above line provides a path to generate the user_defined_templates.v file. +Now we can return to the root directory and run this command again: + +``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` + +Fixing the Error with user_defined_templates.v +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The `user_defined_templates.v`_ file can be found starting from the root directory and entering: + +``vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v`` + +This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. +To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should resemble :numref:`fig_modified_templates_file` + +.. _fig_modified_templates_file: .. figure:: ./figures/modified_user_defined_templates_file.png :scale: 50% - -We can now link this definition into the architecture file and run the task script again. -There should be no errors if this is done correctly. + The Finished user_defined_templates.v File +We can now link this user_defined_templates.v into k6_frac_N10_adder_chain_40nm_openfpga.xml. + +.. note:: Be sure to select the run where you modified the user_defined_templates.v! + +From the OpenFPGA root directory, run: + +``vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml`` + +At line 187 in verilog_netlist, put in: + +``${OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/**YOUR_RUN_NUMBER**/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v`` + +Finally, rerun this command from the OpenFPGA root directory to ensure it is working: + +``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` + + +.. _user_defined_templates.v: https://openfpga--274.org.readthedocs.build/en/274/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v From b194e9c39584e1e885238507516820acd40698a7 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:37:44 -0600 Subject: [PATCH 047/352] Update index.rst Include link to user_defined_temp_tutorial file --- docs/source/tutorials/arch_modeling/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/tutorials/arch_modeling/index.rst b/docs/source/tutorials/arch_modeling/index.rst index 1b643641d..06c7690d4 100644 --- a/docs/source/tutorials/arch_modeling/index.rst +++ b/docs/source/tutorials/arch_modeling/index.rst @@ -8,3 +8,4 @@ Architecture Modeling :maxdepth: 2 quick_start + user_defined_temp_tutorial From 4317f7add741a9cf9b8c11f2300622518ce6cf4b Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:50:52 -0600 Subject: [PATCH 048/352] Update file to display images w/caps --- .../arch_modeling/user_defined_temp_tutorial.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 84a0e2834..40b1e9452 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -18,7 +18,10 @@ Go to line 187 and remove the path for the verilog_netlist. The modified file sh .. figure:: ./figures/modified_arch_file.png :scale: 50% - The Modified k6_frac_N10_adder_chain_40nm_openfpga.xml File + + +The Modified k6_frac_N10_adder_chain_40nm_openfpga.xml File + Motivation ~~~~~~~~~~ From the OpenFPGA root directory run the command @@ -31,7 +34,10 @@ Running this command should fail and produce output similar to :numref:`fig_Erro .. figure:: ./figures/Error_log.png :scale: 50% - Errors Created by k6_frac_N10_adder_chain_40nm_openfpga.xml File Modification + + +Errors Created by k6_frac_N10_adder_chain_40nm_openfpga.xml File Modification + This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. Fixing the Error @@ -55,9 +61,13 @@ This file contains user-defined verilog modules that are found in the openfpga_c To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should resemble :numref:`fig_modified_templates_file` .. _fig_modified_templates_file: + .. figure:: ./figures/modified_user_defined_templates_file.png :scale: 50% - The Finished user_defined_templates.v File + + +The Finished user_defined_templates.v File + We can now link this user_defined_templates.v into k6_frac_N10_adder_chain_40nm_openfpga.xml. .. note:: Be sure to select the run where you modified the user_defined_templates.v! From 07f05cc9425b2e0ee2cfe3acaef0bc7daf733bc4 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:16:27 -0600 Subject: [PATCH 049/352] Update user_defined_temp_tutorial.rst Update to remove two images that were hard to read on the webpage and replace with code blocks --- .../user_defined_temp_tutorial.rst | 77 +++++++++++++------ 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 40b1e9452..27f4289de 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -5,22 +5,16 @@ Introduction and Setup **In this tutorial, we will** - Provide motivation for generating the user_defined_templates.v verilog file - Go through a generated user_defined_templates.v file to demonstrate how to use it -Through this example, we will motivate and show how to use the user_defined_templates.v file. +Through this example, we will motivate and show how to use the ``user_defined_templates.v`` file. For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: ``vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml`` -Go to line 187 and remove the path for the verilog_netlist. The modified file should look like :numref:`fig_modified_arch_file`. +Go to line 187 and replace it with: -.. _fig_modified_arch_file: - -.. figure:: ./figures/modified_arch_file.png - :scale: 50% - - -The Modified k6_frac_N10_adder_chain_40nm_openfpga.xml File +```` Motivation ~~~~~~~~~~ @@ -36,17 +30,17 @@ Running this command should fail and produce output similar to :numref:`fig_Erro :scale: 50% -Errors Created by k6_frac_N10_adder_chain_40nm_openfpga.xml File Modification +Errors Created by ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` File Modification -This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The user_defined_templates.v file provides a module template for incorporating Hard IPs with no external library into the architecture. +This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The `user_defined_templates.v` file provides a module template for incorporating Hard IPs with no external library into the architecture. Fixing the Error ~~~~~~~~~~~~~~~~ -This error can be resolved by putting the following line back into the k6_frac_N10_adder_chain_40nm_openfpga.xml file at line 187 in the verilog_netlist location: +This error can be resolved by putting the following line back into the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file at line 187 in the verilog_netlist location: ``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` -The above line provides a path to generate the user_defined_templates.v file. +The above line provides a path to generate the ``user_defined_templates.v`` file. Now we can return to the root directory and run this command again: ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` @@ -58,19 +52,58 @@ The `user_defined_templates.v`_ file can be found starting from the root directo ``vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v`` This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. -To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). The file should resemble :numref:`fig_modified_templates_file` +To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_templates.v`` file with the following: -.. _fig_modified_templates_file: +``//------------------------------------------- +// FPGA Synthesizable Verilog Netlist +// Description: Template for user-defined Verilog modules +// Author: Xifan TANG +// Organization: University of Utah +// Date: Fri Mar 19 10:05:32 2021 +//------------------------------------------- +//----- Time scale ----- +`timescale 1ns / 1ps -.. figure:: ./figures/modified_user_defined_templates_file.png - :scale: 50% - - -The Finished user_defined_templates.v File -We can now link this user_defined_templates.v into k6_frac_N10_adder_chain_40nm_openfpga.xml. -.. note:: Be sure to select the run where you modified the user_defined_templates.v! +// ----- Template Verilog module for ADDF ----- +//----- Default net type ----- +`default_nettype none + +// ----- Verilog module for ADDF ----- +module ADDF(A, + B, + CI, + SUM, + CO); +//----- INPUT PORTS ----- +input [0:0] A; +//----- INPUT PORTS ----- +input [0:0] B; +//----- INPUT PORTS ----- +input [0:0] CI; +//----- OUTPUT PORTS ----- +output [0:0] SUM; +//----- OUTPUT PORTS ----- +output [0:0] CO; + +//----- BEGIN wire-connection ports ----- +//----- END wire-connection ports ----- + + +//----- BEGIN Registered ports ----- +//----- END Registered ports ----- + +// ----- Internal logic should start here ----- + assign SUM = A ^ B ^ CI; + assign CO = (A & B) | (A & CI) | (B & CI); +// ----- Internal logic should end here ----- +endmodule +// ----- END Verilog module for ADDF -----`` + +We can now link this ``user_defined_templates.v`` into ``k6_frac_N10_adder_chain_40nm_openfpga.xml``. + +.. note:: Be sure to select the run where you modified the ``user_defined_templates.v``! From the OpenFPGA root directory, run: From 59ecaae23bd6d1501d727e4132f9fe4a8186bfa5 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:21:44 -0600 Subject: [PATCH 050/352] Update to use code-block syntax --- .../arch_modeling/user_defined_temp_tutorial.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 27f4289de..c999a774e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -14,7 +14,8 @@ To follow along, go to the root directory of OpenFPGA and enter: Go to line 187 and replace it with: -```` +.. code-block:: xml + Motivation ~~~~~~~~~~ @@ -54,7 +55,8 @@ The `user_defined_templates.v`_ file can be found starting from the root directo This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_templates.v`` file with the following: -``//------------------------------------------- +.. code-block:: verilog +//------------------------------------------- // FPGA Synthesizable Verilog Netlist // Description: Template for user-defined Verilog modules // Author: Xifan TANG @@ -99,7 +101,7 @@ output [0:0] CO; assign CO = (A & B) | (A & CI) | (B & CI); // ----- Internal logic should end here ----- endmodule -// ----- END Verilog module for ADDF -----`` +// ----- END Verilog module for ADDF ----- We can now link this ``user_defined_templates.v`` into ``k6_frac_N10_adder_chain_40nm_openfpga.xml``. From 34a1df858b827a34e0cde47626d9bc7e49dcf575 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:25:32 -0600 Subject: [PATCH 051/352] Fix code-block syntax for XML --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index c999a774e..362607907 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -14,7 +14,8 @@ To follow along, go to the root directory of OpenFPGA and enter: Go to line 187 and replace it with: -.. code-block:: xml +.. code-block:: XML + Motivation @@ -55,7 +56,8 @@ The `user_defined_templates.v`_ file can be found starting from the root directo This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_templates.v`` file with the following: -.. code-block:: verilog +.. code-block:: Verilog + //------------------------------------------- // FPGA Synthesizable Verilog Netlist // Description: Template for user-defined Verilog modules From 191ce358c78a4f8208104d66f9607ef4eff227af Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:29:34 -0600 Subject: [PATCH 052/352] Indent code-blocks --- .../user_defined_temp_tutorial.rst | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 362607907..5d018c68d 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -16,7 +16,7 @@ Go to line 187 and replace it with: .. code-block:: XML - + Motivation ~~~~~~~~~~ @@ -58,52 +58,52 @@ To implement our own ADDF module, we need to remove all other module definitions .. code-block:: Verilog -//------------------------------------------- -// FPGA Synthesizable Verilog Netlist -// Description: Template for user-defined Verilog modules -// Author: Xifan TANG -// Organization: University of Utah -// Date: Fri Mar 19 10:05:32 2021 -//------------------------------------------- -//----- Time scale ----- -`timescale 1ns / 1ps + //------------------------------------------- + // FPGA Synthesizable Verilog Netlist + // Description: Template for user-defined Verilog modules + // Author: Xifan TANG + // Organization: University of Utah + // Date: Fri Mar 19 10:05:32 2021 + //------------------------------------------- + //----- Time scale ----- + `timescale 1ns / 1ps + + + + // ----- Template Verilog module for ADDF ----- + //----- Default net type ----- + `default_nettype none + + // ----- Verilog module for ADDF ----- + module ADDF(A, + B, + CI, + SUM, + CO); + //----- INPUT PORTS ----- + input [0:0] A; + //----- INPUT PORTS ----- + input [0:0] B; + //----- INPUT PORTS ----- + input [0:0] CI; + //----- OUTPUT PORTS ----- + output [0:0] SUM; + //----- OUTPUT PORTS ----- + output [0:0] CO; + + //----- BEGIN wire-connection ports ----- + //----- END wire-connection ports ----- + //----- BEGIN Registered ports ----- + //----- END Registered ports ----- -// ----- Template Verilog module for ADDF ----- -//----- Default net type ----- -`default_nettype none - -// ----- Verilog module for ADDF ----- -module ADDF(A, - B, - CI, - SUM, - CO); -//----- INPUT PORTS ----- -input [0:0] A; -//----- INPUT PORTS ----- -input [0:0] B; -//----- INPUT PORTS ----- -input [0:0] CI; -//----- OUTPUT PORTS ----- -output [0:0] SUM; -//----- OUTPUT PORTS ----- -output [0:0] CO; - -//----- BEGIN wire-connection ports ----- -//----- END wire-connection ports ----- - - -//----- BEGIN Registered ports ----- -//----- END Registered ports ----- - -// ----- Internal logic should start here ----- - assign SUM = A ^ B ^ CI; - assign CO = (A & B) | (A & CI) | (B & CI); -// ----- Internal logic should end here ----- -endmodule -// ----- END Verilog module for ADDF ----- + // ----- Internal logic should start here ----- + assign SUM = A ^ B ^ CI; + assign CO = (A & B) | (A & CI) | (B & CI); + // ----- Internal logic should end here ----- + endmodule + // ----- END Verilog module for ADDF ----- We can now link this ``user_defined_templates.v`` into ``k6_frac_N10_adder_chain_40nm_openfpga.xml``. From ccfcae88d7487e45bb2e5fce1771a6b344fad2a1 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:41:55 -0600 Subject: [PATCH 053/352] Update to remove clunky image with code-block --- .../user_defined_temp_tutorial.rst | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 5d018c68d..0796bb68e 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -24,15 +24,39 @@ From the OpenFPGA root directory run the command ``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` -Running this command should fail and produce output similar to :numref:`fig_Error_log`. +Running this command should fail and produce these errors: -.. _fig_Error_log: +.. code-block:: XML + + ERROR - iverilog_verification run failed with returncode 21 + ERROR - command iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>././SRC/lb/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder.v:50: error: Unknown module type: ADDF + ERROR - -->>21 error(s) during elaboration. + ERROR - Current working directory : /research/ece/lnis/USERS/leaptrot/OpenFPGA/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/run019/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH + ERROR - Failed to run iverilog_verification task + ERROR - Exiting . . . . . . +This error log can be found by running the following command from the root directory: -.. figure:: ./figures/Error_log.png - :scale: 50% - - -Errors Created by ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` File Modification +``cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log`` This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The `user_defined_templates.v` file provides a module template for incorporating Hard IPs with no external library into the architecture. From 3dea033981b6a87f8b6c4b72ba2ae9122f2f662e Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 18:12:27 -0600 Subject: [PATCH 054/352] Implement more code blocks for cleaner page --- .../user_defined_temp_tutorial.rst | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 0796bb68e..a39892b65 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -10,7 +10,9 @@ Through this example, we will motivate and show how to use the ``user_defined_te For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: -``vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml`` +.. code-block:: XML + + vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml Go to line 187 and replace it with: @@ -22,7 +24,9 @@ Motivation ~~~~~~~~~~ From the OpenFPGA root directory run the command -``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` +.. code-block:: XML + + python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs Running this command should fail and produce these errors: @@ -56,26 +60,34 @@ Running this command should fail and produce these errors: ERROR - Exiting . . . . . . This error log can be found by running the following command from the root directory: -``cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log`` +.. code-block:: XML + + cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The `user_defined_templates.v` file provides a module template for incorporating Hard IPs with no external library into the architecture. Fixing the Error ~~~~~~~~~~~~~~~~ -This error can be resolved by putting the following line back into the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` file at line 187 in the verilog_netlist location: +This error can be resolved by replacing the line 187 of ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` with the following: -``${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v`` +.. code-block:: XML + + The above line provides a path to generate the ``user_defined_templates.v`` file. Now we can return to the root directory and run this command again: -``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` +.. code-block:: XML + + python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs Fixing the Error with user_defined_templates.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `user_defined_templates.v`_ file can be found starting from the root directory and entering: -``vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v`` +.. code-block:: XML + + vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_templates.v`` file with the following: @@ -135,15 +147,21 @@ We can now link this ``user_defined_templates.v`` into ``k6_frac_N10_adder_chain From the OpenFPGA root directory, run: -``vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml`` +.. code-block:: XML + + vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml At line 187 in verilog_netlist, put in: -``${OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/**YOUR_RUN_NUMBER**/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v`` +.. code-block:: XML + + ${OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/**YOUR_RUN_NUMBER**/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v Finally, rerun this command from the OpenFPGA root directory to ensure it is working: -``python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs`` +.. code-block:: XML + + python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs .. _user_defined_templates.v: https://openfpga--274.org.readthedocs.build/en/274/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v From 16cefdba28f3ecc6986eb9d07d7911533ab49a79 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 18:19:14 -0600 Subject: [PATCH 055/352] Fix minor changes in page --- .../tutorials/arch_modeling/user_defined_temp_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index a39892b65..6ed47f334 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -64,7 +64,7 @@ This error log can be found by running the following command from the root direc cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log -This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term verilog_netlist. The `user_defined_templates.v` file provides a module template for incorporating Hard IPs with no external library into the architecture. +This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term `verilog_netlist`. The ``user_defined_templates.v`` file provides a module template for incorporating Hard IPs with no external library into the architecture. Fixing the Error ~~~~~~~~~~~~~~~~ From 8ee86d78dd095436ef50b9e66a79ed38e4669d74 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 23 Mar 2021 20:50:54 -0600 Subject: [PATCH 056/352] Implement some of the final changes --- .../user_defined_temp_tutorial.rst | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index 6ed47f334..d94ed9315 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -1,20 +1,20 @@ -Integrating Custom Verilog Modules with user_defined_templates.v +Integrating Custom Verilog Modules with user_defined_template.v ================================================================ Introduction and Setup ~~~~~~~~~~~~~~~~~~~~~~ **In this tutorial, we will** - - Provide motivation for generating the user_defined_templates.v verilog file - - Go through a generated user_defined_templates.v file to demonstrate how to use it -Through this example, we will motivate and show how to use the ``user_defined_templates.v`` file. + - Provide motivation for generating the user_defined_template.v verilog file + - Go through a generated user_defined_template.v file to demonstrate how to use it +Through this example, we will motivate and show how to use the ``user_defined_template.v`` file. For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: -.. code-block:: XML +.. code-block:: bash vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml -Go to line 187 and replace it with: +Go to **LINE187** and replace it with: .. code-block:: XML @@ -24,13 +24,13 @@ Motivation ~~~~~~~~~~ From the OpenFPGA root directory run the command -.. code-block:: XML +.. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs Running this command should fail and produce these errors: -.. code-block:: XML +.. code-block:: bash ERROR - iverilog_verification run failed with returncode 21 ERROR - command iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb @@ -60,37 +60,38 @@ Running this command should fail and produce these errors: ERROR - Exiting . . . . . . This error log can be found by running the following command from the root directory: -.. code-block:: XML +.. code-block:: bash cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log -This command failed during the verification step because the path to the module definition for ADDF is missing. In our architecture file, user-defined verilog modules are those ```` with the key term `verilog_netlist`. The ``user_defined_templates.v`` file provides a module template for incorporating Hard IPs with no external library into the architecture. +This command failed during the verification step because the path to the module definition for **ADDF** is missing. In our architecture file, user-defined verilog modules are those ```` with the key term `verilog_netlist`. The ``user_defined_template.v`` file provides a module template for incorporating Hard IPs with no external library into the architecture. Fixing the Error ~~~~~~~~~~~~~~~~ -This error can be resolved by replacing the line 187 of ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` with the following: +This error can be resolved by replacing the **LINE187** of ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` with the following: .. code-block:: XML -The above line provides a path to generate the ``user_defined_templates.v`` file. +The above line provides a path to generate the ``user_defined_template.v`` file. Now we can return to the root directory and run this command again: -.. code-block:: XML +.. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -Fixing the Error with user_defined_templates.v +Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The `user_defined_templates.v`_ file can be found starting from the root directory and entering: +The `user_defined_template.v`_ file can be found starting from the root directory and entering: -.. code-block:: XML +.. code-block:: bash - vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v + vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_template.v -This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. -To implement our own ADDF module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_templates.v`` file with the following: +.. note:: This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. + +To implement our own **ADDF** module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_template.v`` file with the following: .. code-block:: Verilog @@ -141,27 +142,27 @@ To implement our own ADDF module, we need to remove all other module definitions endmodule // ----- END Verilog module for ADDF ----- -We can now link this ``user_defined_templates.v`` into ``k6_frac_N10_adder_chain_40nm_openfpga.xml``. +We can now link this ``user_defined_template.v`` into ``k6_frac_N10_adder_chain_40nm_openfpga.xml``. -.. note:: Be sure to select the run where you modified the ``user_defined_templates.v``! +.. note:: Be sure to select the run where you modified the ``user_defined_template.v``! From the OpenFPGA root directory, run: -.. code-block:: XML +.. code-block:: bash vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml -At line 187 in verilog_netlist, put in: +At **LINE187** in verilog_netlist, put in: .. code-block:: XML - ${OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/**YOUR_RUN_NUMBER**/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_templates.v + ${OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/**YOUR_RUN_NUMBER**/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_template.v Finally, rerun this command from the OpenFPGA root directory to ensure it is working: -.. code-block:: XML +.. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -.. _user_defined_templates.v: https://openfpga--274.org.readthedocs.build/en/274/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v +.. _user_defined_template.v: https://openfpga--274.org.readthedocs.build/en/274/manual/fpga_verilog/fabric_netlist/#cmdoption-arg-user_defined_templates.v From b8b024048ec491a8b6e8560bb835a15c81d19770 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 30 Mar 2021 21:54:46 -0600 Subject: [PATCH 057/352] Add first draft for Open Cell Libraries tutorial --- .../open_cell_libraries_tutorial.rst | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst new file mode 100644 index 000000000..2b68f1166 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -0,0 +1,221 @@ +Using Open-source Cell Libraries with OpenFPGA Architectures +============================================================ + +Introduction +~~~~~~~~~~~~ + +**In this tutorial, we will** + - Clone the Skywater Processor Development Kit into the OpenFPGA root directory + - Use Skywater's PDK cell library to create an OR Gate circuit model for OpenFPGA + - Verify that the cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave +Through this example, we will show how to bind open-source cell library files with OpenFPGA Architectures. + +Create and Verify the Control Circuit Model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For this tutorial, we will first create a control that we will use to compare the final product of this tutorial with. The final product will be an **OR2** circuit model referencing Skywater's PDK cell library. +To follow along, go to the root directory of OpenFPGA and enter: + +.. code-block:: bash + + python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs + +This will run a prebuilt task with OpenFPGA cell libraries. When the task is finished, there will be many auto-generated files to look through. For this tutorial, we are interested +in the ``luts.v`` and ``and2_formal.vcd`` files. The ``luts.v`` file will eventually have the changes we will implement in the tutorial, +and the ``and2_formal.vcd`` file will have the resulting waveforms from the simulation run by the task. To open the ``luts.v`` file, run the following command: + +.. code-block:: bash + + vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.v + +The ``luts.v`` file represents a Look Up Table within the OpenFPGA architecture. The important lines of this file for the tutorial are **LINE58**, **LINE59**, and **LINE72** to **LINE80**. +These lines show the instantiation of OpenFPGA's **OR2** cell library. + +**LINE58**: + +.. code-block:: verilog + + wire [0:0] OR2_0_out; + +**LINE59**: + +.. code-block:: verilog + + wire [0:0] OR2_1_out; + +**LINE72** to **LINE80**: + +.. code-block:: verilog + + OR2 OR2_0_ ( + .a(mode[0:0]), + .b(in[4]), + .out(OR2_0_out)); + + OR2 OR2_1_ ( + .a(mode[1]), + .b(in[5]), + .out(OR2_1_out)); + +We will also need to look at the control's simulation waveforms. Viewing the waveforms is done through GTKWave with the following command: + +.. code-block:: bash + + gtkwave openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & + +The simulation waveforms should look similar to the following :numref:`fig_control_output`: + +.. _fig_control_output: + +.. figure:: ./figures/control_output.svg + :scale: 100% + + Control Circuit Model's Simulation Waveforms + +.. note:: The waveform inputs do not need to exactly match because the testbench provides input in random intervals. + +We have now finished creating the control and viewing the important sections for this tutorial. We can now incorporate Skywater's cell library to create a new circuit model. + +Clone Skywater PDK into OpenFPGA +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We will be using the open-source Skywater Processor Development Kit to aid us in creating our circuit model. We start by cloning the Skywater PDK github repository into the OpenFPGA root directory. +Run the following command in the root directory of OpenFPGA: + +.. code-block:: bash + + git clone https://github.com/google/skywater-pdk.git + +Once the repository has been cloned, we need to build the cell libraries by running the following command in the Skywater PDK root directory: + +.. code-block:: bash + + SUBMODULE_VERSION=latest make submodules -j3 || make submodules -j1 + +This will take some time to complete due to the size of the libraries. Once the libraries are made, creating the circuit model can begin. + +Create and Verify the Cell Library Circuit Model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create the circuit model, we will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` OpenFPGA architecture file. We will remove the circuit model +for OpenFPGA's **OR2** gate, replace the circuit model with one referencing the Skywater cell library, and modify the LUT that references the old **OR2** +circuit model to reference our new circuit model. We begin by running the following command in the root directory: + +.. code-block:: bash + + vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml + +We begin the circuit model creation process by replacing **LINE67** to **LINE81** with the following: + +.. code-block:: xml + + + + + + + + + + +.. note:: The name of the circuit model must be consistent with the standard cell! + +The most significant differences from the control in this section are changing the ``name`` and ``prefix`` to match the module name from Skywater's cell library and including a path +to the verilog file using ``verilog_netlist``. The second change to ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` is at **LINE160**, where we will be replacing the line with the following: + +.. code-block:: xml + + + +This change replaces the input of the LUT with our new circuit model. Everything is in place to begin verification. + +Verification begins by running the following command: + +.. code-block:: bash + + python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs + +The task may output this error: + +.. code-block:: bash + + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - iverilog_verification run failed with returncode 1 + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - command iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - -->>error: Unable to find the root module "and2_top_formal_verification_random_tb" in the Verilog source. + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - -->>1 error(s) during elaboration. + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - Current working directory : OpenFPGA/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/run057/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - Failed to run iverilog_verification task + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - Exiting . . . . . . + ERROR (00_and2_MIN_ROUTE_CHAN_WIDTH) - Failed to execute openfpga flow - 00_and2_MIN_ROUTE_CHAN_WIDTH + + +This error has occurred because IVerilog could not find the path to the Skywater PDK Cell Library we have selected. To fix this, we need to go to the +``iverilog_output.txt`` file found here: + +.. code-block:: bash + + emacs openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/iverilog_output.txt + +Replace all the text within ``iverilog_output.txt`` with the following: + +.. code-block:: bash + + iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 + +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our ``From Verilog to Verification``_ tutorial. From the root +directory, run the following commands: + +.. code-block:: bash + + cd openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/ + + source iverilog_output.txt + + vvp compiled_and2 + +With IVerilog complete, we can verify the cell library has been bound correctly by viewing the ``luts.v`` file and the waveforms with GTKWave. + +From the root directory, view the ``luts.v`` file with this command: + +.. code-block:: bash + + vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.v + +Scrolling through ``luts.v``, this should be present in the file: + +.. code-block:: verilog + + wire [0:0] sky130_fd_sc_ls__or2_1_0_X; + wire [0:0] sky130_fd_sc_ls__or2_1_1_X; + + // ----- BEGIN Local short connections ----- + // ----- END Local short connections ----- + // ----- BEGIN Local output short connections ----- + // ----- END Local output short connections ----- + + sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_0_ ( + .A(mode[0:0]), + .B(in[4]), + .X(sky130_fd_sc_ls__or2_1_0_X)); + + sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_1_ ( + .A(mode[1]), + .B(in[5]), + .X(sky130_fd_sc_ls__or2_1_1_X)); + +We can check the waveforms as well to see if they are similar with the command: + +.. code-block:: bash + + gtkwave openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd & + +The simulation waveforms should look similar to the following :numref:`fig_custom_output`: + +.. _fig_custom_output: + +.. figure:: ./figures/custom_output.svg + :scale: 100% + + Custom Circuit Model's Simulation Waveforms + +We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, reach out to us on github. + +.. _From Verilog to Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ \ No newline at end of file From f963be4caeb5e489c9607c3b977c30448f932fc2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 30 Mar 2021 21:56:43 -0600 Subject: [PATCH 058/352] Add files via upload --- .../figures/Control_Waveforms.svg | 270 ++++++++++++++++++ .../figures/Custom_Waveforms.svg | 130 +++++++++ 2 files changed, 400 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg create mode 100644 docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg new file mode 100644 index 000000000..7900e5d06 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + +0 + + + + + + + + + + + +10 ns + + + + + + + + + + + +20 ns + + + + + + + + + + + +30 ns + + + + + + + + + +40 ns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Time + + +a=0 + + +b=1 + + +out_c_gfpga=0 + + + diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg new file mode 100644 index 000000000..4d34b8d98 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + +0 + + + + + + + + + + + +10 ns + + + + + +20 ns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Time + + +a=1 + + +b=0 + + +out_c_gfpga=0 + + + From 36a6870cc05a4bf4a595a9f422cb51952f97194f Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Tue, 30 Mar 2021 21:59:18 -0600 Subject: [PATCH 059/352] Update tutorial to display waveforms --- .../arch_modeling/open_cell_libraries_tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 2b68f1166..391aea66f 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -66,7 +66,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: -.. figure:: ./figures/control_output.svg +.. figure:: ./figures/Control_Waveforms.svg :scale: 100% Control Circuit Model's Simulation Waveforms @@ -211,11 +211,11 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: -.. figure:: ./figures/custom_output.svg +.. figure:: ./figures/Custom_Waveforms.svg :scale: 100% Custom Circuit Model's Simulation Waveforms We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, reach out to us on github. -.. _From Verilog to Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ \ No newline at end of file +.. _From Verilog to Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ From f8da09a80e846fbf75b3c0bb93098969daf4cdb7 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 31 Mar 2021 10:04:00 -0600 Subject: [PATCH 060/352] Update to include cell_library tutorial --- docs/source/tutorials/arch_modeling/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/tutorials/arch_modeling/index.rst b/docs/source/tutorials/arch_modeling/index.rst index 06c7690d4..13ded287e 100644 --- a/docs/source/tutorials/arch_modeling/index.rst +++ b/docs/source/tutorials/arch_modeling/index.rst @@ -9,3 +9,4 @@ Architecture Modeling quick_start user_defined_temp_tutorial + open_cell_library_tutorial From c1036c6ac4b6824c4ce36047fac91b4df8f3f030 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Wed, 31 Mar 2021 10:04:51 -0600 Subject: [PATCH 061/352] Match spelling to file name for cell_libraries --- docs/source/tutorials/arch_modeling/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/index.rst b/docs/source/tutorials/arch_modeling/index.rst index 13ded287e..c7f53ef3d 100644 --- a/docs/source/tutorials/arch_modeling/index.rst +++ b/docs/source/tutorials/arch_modeling/index.rst @@ -9,4 +9,4 @@ Architecture Modeling quick_start user_defined_temp_tutorial - open_cell_library_tutorial + open_cell_libraries_tutorial From 5f01e5e7a7dfff485bf56aa442f04925efc24a63 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 09:54:54 -0600 Subject: [PATCH 062/352] Update file --- .../open_cell_libraries_tutorial.rst | 354 +++++++++++++++--- 1 file changed, 304 insertions(+), 50 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 391aea66f..bae8011a4 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -1,62 +1,186 @@ -Using Open-source Cell Libraries with OpenFPGA Architectures -============================================================ +Build an FPGA fabric using Standard Cell Libraries +================================================== Introduction ~~~~~~~~~~~~ **In this tutorial, we will** - - Clone the Skywater Processor Development Kit into the OpenFPGA root directory - - Use Skywater's PDK cell library to create an OR Gate circuit model for OpenFPGA - - Verify that the cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave -Through this example, we will show how to bind open-source cell library files with OpenFPGA Architectures. + - Showcase how to create an architecture description based on standard cells, using OpenFPGA's circuit modeling language + - Use Skywater's Processor Development Kit (``PDK``_) cell library to create an OR Gate circuit model for OpenFPGA + - Verify that the standard cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave +Through this example, we will show how to bind standard cell library files with OpenFPGA Architectures. -Create and Verify the Control Circuit Model -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For this tutorial, we will first create a control that we will use to compare the final product of this tutorial with. The final product will be an **OR2** circuit model referencing Skywater's PDK cell library. +.. note:: We showcase the methodology by considering the open-source Skywater 130nm PDK so that users can easily reproduce the results. + +Create and Verify the OpenFPGA Circuit Model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In this tutorial, we focus on binding a 2-input **OR** gate from a standard cell library to a circuit model in OpenFPGA's architecture description file. Note that the approach can be generalized to any circuit model. For this tutorial, we start with an example where the HDL netlist of an 2-input **OR** gate that is auto-generated by OpenFPGA. After updating the architecture file, the auto-generated HDL netlist by OpenFPGA will directly instantiate a standard cell from the open-source Skywater 130nm PDK library. To follow along, go to the root directory of OpenFPGA and enter: .. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -This will run a prebuilt task with OpenFPGA cell libraries. When the task is finished, there will be many auto-generated files to look through. For this tutorial, we are interested -in the ``luts.v`` and ``and2_formal.vcd`` files. The ``luts.v`` file will eventually have the changes we will implement in the tutorial, -and the ``and2_formal.vcd`` file will have the resulting waveforms from the simulation run by the task. To open the ``luts.v`` file, run the following command: +This will run a prebuilt task with OpenFPGA cell libraries. When the task is finished, there will be many auto-generated files to look through. For this tutorial, we are interested in the ``luts.v`` and ``and2_formal.vcd`` files. The **OR2** gate is used as a control circuit in the **lut6** circuit model, and the ``and2_formal.vcd`` file will have the resulting waveforms from the simulation run by the task. To open the ``luts.v`` file, run the following command: .. code-block:: bash vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/luts.v -The ``luts.v`` file represents a Look Up Table within the OpenFPGA architecture. The important lines of this file for the tutorial are **LINE58**, **LINE59**, and **LINE72** to **LINE80**. +.. note:: Users can find full details about netlist organization in our documentation: https://openfpga.readthedocs.io/en/master/manual/fpga_verilog/fabric_netlist/ + +The ``luts.v`` file represents a Look Up Table within the OpenFPGA architecture. The important lines of this file for the tutorial are highlighted below. These lines show the instantiation of OpenFPGA's **OR2** cell library. -**LINE58**: - .. code-block:: verilog + :emphasize-lines: 58,59,72,73,74,75,76,77,78,79,80 + + //------------------------------------------- + // FPGA Synthesizable Verilog Netlist + // Description: Look-Up Tables + // Author: Xifan TANG + // Organization: University of Utah + // Date: Tue Mar 30 15:25:03 2021 + //------------------------------------------- + //----- Time scale ----- + `timescale 1ns / 1ps + + //----- Default net type ----- + `default_nettype none + + // ----- Verilog module for frac_lut6 ----- + module frac_lut6(in, + sram, + sram_inv, + mode, + mode_inv, + lut4_out, + lut5_out, + lut6_out); + //----- INPUT PORTS ----- + input [0:5] in; + //----- INPUT PORTS ----- + input [0:63] sram; + //----- INPUT PORTS ----- + input [0:63] sram_inv; + //----- INPUT PORTS ----- + input [0:1] mode; + //----- INPUT PORTS ----- + input [0:1] mode_inv; + //----- OUTPUT PORTS ----- + output [0:3] lut4_out; + //----- OUTPUT PORTS ----- + output [0:1] lut5_out; + //----- OUTPUT PORTS ----- + output [0:0] lut6_out; + + //----- BEGIN wire-connection ports ----- + wire [0:5] in; + wire [0:3] lut4_out; + wire [0:1] lut5_out; + wire [0:0] lut6_out; + //----- END wire-connection ports ----- + + + //----- BEGIN Registered ports ----- + //----- END Registered ports ----- + + + wire [0:0] INVTX1_0_out; + wire [0:0] INVTX1_1_out; + wire [0:0] INVTX1_2_out; + wire [0:0] INVTX1_3_out; + wire [0:0] INVTX1_4_out; + wire [0:0] INVTX1_5_out; wire [0:0] OR2_0_out; - -**LINE59**: - -.. code-block:: verilog - wire [0:0] OR2_1_out; + wire [0:0] buf4_0_out; + wire [0:0] buf4_1_out; + wire [0:0] buf4_2_out; + wire [0:0] buf4_3_out; + wire [0:0] buf4_4_out; + wire [0:0] buf4_5_out; + + // ----- BEGIN Local short connections ----- + // ----- END Local short connections ----- + // ----- BEGIN Local output short connections ----- + // ----- END Local output short connections ----- + + OR2 OR2_0_ ( + .a(mode[0:0]), + .b(in[4]), + .out(OR2_0_out)); + + OR2 OR2_1_ ( + .a(mode[1]), + .b(in[5]), + .out(OR2_1_out)); + + INVTX1 INVTX1_0_ ( + .in(in[0:0]), + .out(INVTX1_0_out)); + + INVTX1 INVTX1_1_ ( + .in(in[1]), + .out(INVTX1_1_out)); + + INVTX1 INVTX1_2_ ( + .in(in[2]), + .out(INVTX1_2_out)); + + INVTX1 INVTX1_3_ ( + .in(in[3]), + .out(INVTX1_3_out)); + + INVTX1 INVTX1_4_ ( + .in(OR2_0_out), + .out(INVTX1_4_out)); + + INVTX1 INVTX1_5_ ( + .in(OR2_1_out), + .out(INVTX1_5_out)); + + buf4 buf4_0_ ( + .in(in[0:0]), + .out(buf4_0_out)); + + buf4 buf4_1_ ( + .in(in[1]), + .out(buf4_1_out)); + + buf4 buf4_2_ ( + .in(in[2]), + .out(buf4_2_out)); + + buf4 buf4_3_ ( + .in(in[3]), + .out(buf4_3_out)); + + buf4 buf4_4_ ( + .in(OR2_0_out), + .out(buf4_4_out)); + + buf4 buf4_5_ ( + .in(OR2_1_out), + .out(buf4_5_out)); + + frac_lut6_mux frac_lut6_mux_0_ ( + .in(sram[0:63]), + .sram({buf4_0_out, buf4_1_out, buf4_2_out, buf4_3_out, buf4_4_out, buf4_5_out}), + .sram_inv({INVTX1_0_out, INVTX1_1_out, INVTX1_2_out, INVTX1_3_out, INVTX1_4_out, INVTX1_5_out}), + .lut4_out(lut4_out[0:3]), + .lut5_out(lut5_out[0:1]), + .lut6_out(lut6_out)); + + endmodule + // ----- END Verilog module for frac_lut6 ----- + + //----- Default net type ----- + `default_nettype none -**LINE72** to **LINE80**: -.. code-block:: verilog - - OR2 OR2_0_ ( - .a(mode[0:0]), - .b(in[4]), - .out(OR2_0_out)); - - OR2 OR2_1_ ( - .a(mode[1]), - .b(in[5]), - .out(OR2_1_out)); - -We will also need to look at the control's simulation waveforms. Viewing the waveforms is done through GTKWave with the following command: +We will also need to look at the control's simulation waveforms. Viewing the waveforms is done through ``GTKWave``_ with the following command: .. code-block:: bash @@ -92,8 +216,8 @@ Once the repository has been cloned, we need to build the cell libraries by runn This will take some time to complete due to the size of the libraries. Once the libraries are made, creating the circuit model can begin. -Create and Verify the Cell Library Circuit Model -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create and Verify the Standard Cell Library Circuit Model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To create the circuit model, we will modify the ``k6_frac_N10_adder_chain_40nm_openfpga.xml`` OpenFPGA architecture file. We will remove the circuit model for OpenFPGA's **OR2** gate, replace the circuit model with one referencing the Skywater cell library, and modify the LUT that references the old **OR2** @@ -160,7 +284,7 @@ Replace all the text within ``iverilog_output.txt`` with the following: iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 -We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our ``From Verilog to Verification``_ tutorial. From the root +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our From Verilog to ``Verification``_ tutorial. From the root directory, run the following commands: .. code-block:: bash @@ -182,24 +306,150 @@ From the root directory, view the ``luts.v`` file with this command: Scrolling through ``luts.v``, this should be present in the file: .. code-block:: verilog - + :emphasize-lines: 58,59,72,73,74,75,76,77,78,79,80 + //------------------------------------------- + // FPGA Synthesizable Verilog Netlist + // Description: Look-Up Tables + // Author: Xifan TANG + // Organization: University of Utah + // Date: Tue Mar 30 20:25:06 2021 + //------------------------------------------- + //----- Time scale ----- + `timescale 1ns / 1ps + + //----- Default net type ----- + `default_nettype none + + // ----- Verilog module for frac_lut6 ----- + module frac_lut6(in, + sram, + sram_inv, + mode, + mode_inv, + lut4_out, + lut5_out, + lut6_out); + //----- INPUT PORTS ----- + input [0:5] in; + //----- INPUT PORTS ----- + input [0:63] sram; + //----- INPUT PORTS ----- + input [0:63] sram_inv; + //----- INPUT PORTS ----- + input [0:1] mode; + //----- INPUT PORTS ----- + input [0:1] mode_inv; + //----- OUTPUT PORTS ----- + output [0:3] lut4_out; + //----- OUTPUT PORTS ----- + output [0:1] lut5_out; + //----- OUTPUT PORTS ----- + output [0:0] lut6_out; + + //----- BEGIN wire-connection ports ----- + wire [0:5] in; + wire [0:3] lut4_out; + wire [0:1] lut5_out; + wire [0:0] lut6_out; + //----- END wire-connection ports ----- + + + //----- BEGIN Registered ports ----- + //----- END Registered ports ----- + + + wire [0:0] INVTX1_0_out; + wire [0:0] INVTX1_1_out; + wire [0:0] INVTX1_2_out; + wire [0:0] INVTX1_3_out; + wire [0:0] INVTX1_4_out; + wire [0:0] INVTX1_5_out; + wire [0:0] buf4_0_out; + wire [0:0] buf4_1_out; + wire [0:0] buf4_2_out; + wire [0:0] buf4_3_out; + wire [0:0] buf4_4_out; + wire [0:0] buf4_5_out; wire [0:0] sky130_fd_sc_ls__or2_1_0_X; wire [0:0] sky130_fd_sc_ls__or2_1_1_X; - + // ----- BEGIN Local short connections ----- // ----- END Local short connections ----- // ----- BEGIN Local output short connections ----- // ----- END Local output short connections ----- + + sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_0_ ( + .A(mode[0:0]), + .B(in[4]), + .X(sky130_fd_sc_ls__or2_1_0_X)); + + sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_1_ ( + .A(mode[1]), + .B(in[5]), + .X(sky130_fd_sc_ls__or2_1_1_X)); + + INVTX1 INVTX1_0_ ( + .in(in[0:0]), + .out(INVTX1_0_out)); + + INVTX1 INVTX1_1_ ( + .in(in[1]), + .out(INVTX1_1_out)); + + INVTX1 INVTX1_2_ ( + .in(in[2]), + .out(INVTX1_2_out)); + + INVTX1 INVTX1_3_ ( + .in(in[3]), + .out(INVTX1_3_out)); + + INVTX1 INVTX1_4_ ( + .in(sky130_fd_sc_ls__or2_1_0_X), + .out(INVTX1_4_out)); + + INVTX1 INVTX1_5_ ( + .in(sky130_fd_sc_ls__or2_1_1_X), + .out(INVTX1_5_out)); + + buf4 buf4_0_ ( + .in(in[0:0]), + .out(buf4_0_out)); + + buf4 buf4_1_ ( + .in(in[1]), + .out(buf4_1_out)); + + buf4 buf4_2_ ( + .in(in[2]), + .out(buf4_2_out)); + + buf4 buf4_3_ ( + .in(in[3]), + .out(buf4_3_out)); + + buf4 buf4_4_ ( + .in(sky130_fd_sc_ls__or2_1_0_X), + .out(buf4_4_out)); + + buf4 buf4_5_ ( + .in(sky130_fd_sc_ls__or2_1_1_X), + .out(buf4_5_out)); + + frac_lut6_mux frac_lut6_mux_0_ ( + .in(sram[0:63]), + .sram({buf4_0_out, buf4_1_out, buf4_2_out, buf4_3_out, buf4_4_out, buf4_5_out}), + .sram_inv({INVTX1_0_out, INVTX1_1_out, INVTX1_2_out, INVTX1_3_out, INVTX1_4_out, INVTX1_5_out}), + .lut4_out(lut4_out[0:3]), + .lut5_out(lut5_out[0:1]), + .lut6_out(lut6_out)); + + endmodule + // ----- END Verilog module for frac_lut6 ----- + + //----- Default net type ----- + `default_nettype none - sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_0_ ( - .A(mode[0:0]), - .B(in[4]), - .X(sky130_fd_sc_ls__or2_1_0_X)); - - sky130_fd_sc_ls__or2_1 sky130_fd_sc_ls__or2_1_1_ ( - .A(mode[1]), - .B(in[5]), - .X(sky130_fd_sc_ls__or2_1_1_X)); We can check the waveforms as well to see if they are similar with the command: @@ -216,6 +466,10 @@ The simulation waveforms should look similar to the following :numref:`fig_custo Custom Circuit Model's Simulation Waveforms -We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, reach out to us on github. +We have now verified that the Skywater PDK Cell Library has been instantiated and bound to the OpenFPGA architecture file. If you have any problems, please reach out to us. -.. _From Verilog to Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ +.. _Verification: https://openfpga.readthedocs.io/en/master/tutorials/design_flow/verilog2verification/ + +.. _PDK: https://github.com/google/skywater-pdk + +.. _GTKWave: https://github.com/gtkwave/gtkwave From bff9e7aecd1381c1cc0c2fe91ef67300f3f21e3c Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:02:26 -0600 Subject: [PATCH 063/352] Update hyperlinks to display properly --- .../arch_modeling/open_cell_libraries_tutorial.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index bae8011a4..f6148cdc7 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -6,7 +6,7 @@ Introduction **In this tutorial, we will** - Showcase how to create an architecture description based on standard cells, using OpenFPGA's circuit modeling language - - Use Skywater's Processor Development Kit (``PDK``_) cell library to create an OR Gate circuit model for OpenFPGA + - Use Skywater's Processor Development Kit (`PDK`_) cell library to create an OR Gate circuit model for OpenFPGA - Verify that the standard cell library file was correctly bound into the selected architecture file by looking at auto-generated OpenFPGA files and checking simulation waveforms in GTKWave Through this example, we will show how to bind standard cell library files with OpenFPGA Architectures. @@ -180,7 +180,7 @@ These lines show the instantiation of OpenFPGA's **OR2** cell library. `default_nettype none -We will also need to look at the control's simulation waveforms. Viewing the waveforms is done through ``GTKWave``_ with the following command: +We will also need to look at the control's simulation waveforms. Viewing the waveforms is done through `GTKWave`_ with the following command: .. code-block:: bash @@ -284,7 +284,7 @@ Replace all the text within ``iverilog_output.txt`` with the following: iverilog -o compiled_and2 ./SRC/and2_include_netlists.v -s and2_top_formal_verification_random_tb -I ${OPENFPGA_PATH}/skywater-pdk/libraries/sky130_fd_sc_ls/latest/cells/or2 -We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our From Verilog to ``Verification``_ tutorial. From the root +We can now manually rerun IVerilog, a tutorial on manually running IVerilog can be found at our From Verilog to `Verification`_ tutorial. From the root directory, run the following commands: .. code-block:: bash @@ -307,6 +307,7 @@ Scrolling through ``luts.v``, this should be present in the file: .. code-block:: verilog :emphasize-lines: 58,59,72,73,74,75,76,77,78,79,80 + //------------------------------------------- // FPGA Synthesizable Verilog Netlist // Description: Look-Up Tables From 6393d111536c6ea52aeadf7997462ee0e8473a9d Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:04:53 -0600 Subject: [PATCH 064/352] Update to highlight correct section of code --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index f6148cdc7..669fc4ef2 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -306,7 +306,7 @@ From the root directory, view the ``luts.v`` file with this command: Scrolling through ``luts.v``, this should be present in the file: .. code-block:: verilog - :emphasize-lines: 58,59,72,73,74,75,76,77,78,79,80 + :emphasize-lines: 64,65,72,73,74,75,76,77,78,79,80 //------------------------------------------- // FPGA Synthesizable Verilog Netlist From 1bbf878498bb1f4f2b01dd9592e96aeca67cccc8 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:13:13 -0600 Subject: [PATCH 065/352] Modify image to have a smaller viewbox --- .../tutorials/arch_modeling/figures/Control_Waveforms.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg index 7900e5d06..004ec3b52 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg @@ -1,6 +1,6 @@ - + From d56ba1c5d7ac88c224bb5a953918742c5cfac412 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:13:51 -0600 Subject: [PATCH 066/352] Modify custom waveform to have a smaller viewbox --- .../source/tutorials/arch_modeling/figures/Custom_Waveforms.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg index 4d34b8d98..044f94d1d 100644 --- a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg +++ b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg @@ -1,6 +1,6 @@ - + From c0256cdd87e5f774157af9a704d43ce7ac6bdbe6 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:22:09 -0600 Subject: [PATCH 067/352] Adjust height and width to see if image changes --- .../tutorials/arch_modeling/figures/Control_Waveforms.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg index 004ec3b52..9199b76bf 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.svg @@ -1,6 +1,6 @@ - + From f03754561ce9a98fd1e042c39bdc0dc50dffdef5 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:27:49 -0600 Subject: [PATCH 068/352] Add control_waveforms with smaller viewbox --- .../figures/Control_Waveforms2.svg | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waveforms2.svg diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms2.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms2.svg new file mode 100644 index 000000000..004ec3b52 --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms2.svg @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + +0 + + + + + + + + + + + +10 ns + + + + + + + + + + + +20 ns + + + + + + + + + + + +30 ns + + + + + + + + + +40 ns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Time + + +a=0 + + +b=1 + + +out_c_gfpga=0 + + + From 69b7c8f37ace135a4acbac240674f76b52238e31 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:32:31 -0600 Subject: [PATCH 069/352] Update to include new control_waveforms file --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 669fc4ef2..6d91e41f4 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -190,7 +190,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: -.. figure:: ./figures/Control_Waveforms.svg +.. figure:: ./figures/Control_Waveforms2.svg :scale: 100% Control Circuit Model's Simulation Waveforms From 96275f9c0e5b1c5d9fe84da3cf1900db8a0ae98a Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:39:20 -0600 Subject: [PATCH 070/352] Modify Control_Waveforms to fix height and width The height and width will now be set to the size of the viewbox --- .../figures/Control_Waveforms3.svg | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg new file mode 100644 index 000000000..9199b76bf --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + +0 + + + + + + + + + + + +10 ns + + + + + + + + + + + +20 ns + + + + + + + + + + + +30 ns + + + + + + + + + +40 ns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Time + + +a=0 + + +b=1 + + +out_c_gfpga=0 + + + From 821847f295a4a0dcf0090456a71402dc0976a820 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:40:51 -0600 Subject: [PATCH 071/352] Update Control_Waveforms3.svg --- .../tutorials/arch_modeling/figures/Control_Waveforms3.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg index 9199b76bf..f87866595 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg @@ -1,6 +1,6 @@ - + From 9849946fabddf5c4606aa84141726cb229717ba2 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:41:12 -0600 Subject: [PATCH 072/352] Update Control_Waveforms3.svg --- .../tutorials/arch_modeling/figures/Control_Waveforms3.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg index f87866595..206677454 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg @@ -1,6 +1,6 @@ - + From 65d2f82b94b447eb8a8e5b5893ec08130af957a7 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:41:29 -0600 Subject: [PATCH 073/352] Update Control_Waveforms3.svg --- .../tutorials/arch_modeling/figures/Control_Waveforms3.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg index 206677454..8290711de 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg @@ -1,6 +1,6 @@ - + From baee023ba226c22efe688f9d4178e465853d51ab Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:41:47 -0600 Subject: [PATCH 074/352] Update Control_Waveforms3.svg --- .../tutorials/arch_modeling/figures/Control_Waveforms3.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg index 8290711de..cf065d3bb 100644 --- a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg +++ b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms3.svg @@ -1,6 +1,6 @@ - + From 4c35df0df3a7792ab377abf0885332cbd09c75fd Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:42:15 -0600 Subject: [PATCH 075/352] Update open_cell_libraries_tutorial.rst --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 6d91e41f4..36fec7b20 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -190,7 +190,7 @@ The simulation waveforms should look similar to the following :numref:`fig_contr .. _fig_control_output: -.. figure:: ./figures/Control_Waveforms2.svg +.. figure:: ./figures/Control_Waveforms3.svg :scale: 100% Control Circuit Model's Simulation Waveforms From cfa2d7042d1c8a8d97d3e6a90fa6ac113e0825eb Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:44:36 -0600 Subject: [PATCH 076/352] Update Custom_Waveforms.svg --- .../source/tutorials/arch_modeling/figures/Custom_Waveforms.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg index 044f94d1d..e5060ac4c 100644 --- a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg +++ b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.svg @@ -1,6 +1,6 @@ - + From 3c27027f7607f9af0de217f3a5128ee0645ce79d Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:46:51 -0600 Subject: [PATCH 077/352] Add files via upload --- .../figures/Custom_Waveforms2.svg | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/Custom_Waveforms2.svg diff --git a/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms2.svg b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms2.svg new file mode 100644 index 000000000..e5060ac4c --- /dev/null +++ b/docs/source/tutorials/arch_modeling/figures/Custom_Waveforms2.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + +0 + + + + + + + + + + + +10 ns + + + + + +20 ns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Time + + +a=1 + + +b=0 + + +out_c_gfpga=0 + + + From b6feecc4c304290db64a3bc6ff8f100315ac8bc5 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:47:36 -0600 Subject: [PATCH 078/352] Update to fix SVG files to show data better --- .../tutorials/arch_modeling/open_cell_libraries_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst index 36fec7b20..bcea52c0c 100644 --- a/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/open_cell_libraries_tutorial.rst @@ -462,7 +462,7 @@ The simulation waveforms should look similar to the following :numref:`fig_custo .. _fig_custom_output: -.. figure:: ./figures/Custom_Waveforms.svg +.. figure:: ./figures/Custom_Waveforms2.svg :scale: 100% Custom Circuit Model's Simulation Waveforms From dc991a912ee88695530d4913f413eeee67484a7a Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:59:18 -0600 Subject: [PATCH 079/352] Update to fix grammar and spelling errors --- .../user_defined_temp_tutorial.rst | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst index d94ed9315..943993aaa 100644 --- a/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst +++ b/docs/source/tutorials/arch_modeling/user_defined_temp_tutorial.rst @@ -3,18 +3,18 @@ Integrating Custom Verilog Modules with user_defined_template.v Introduction and Setup ~~~~~~~~~~~~~~~~~~~~~~ **In this tutorial, we will** - - Provide motivation for generating the user_defined_template.v verilog file + - Provide the motivation for generating the user_defined_template.v verilog file - Go through a generated user_defined_template.v file to demonstrate how to use it -Through this example, we will motivate and show how to use the ``user_defined_template.v`` file. +Through this example, we will show how and when to use the ``user_defined_template.v`` file. -For this examaple, we are using a modified version of the hard adder task that comes with OpenFPGA. +For this example, we are using a modified version of the hard adder task that comes with OpenFPGA. To follow along, go to the root directory of OpenFPGA and enter: .. code-block:: bash vi openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml -Go to **LINE187** and replace it with: +Go to **LINE187** and replace **LINE187** with: .. code-block:: XML @@ -22,13 +22,13 @@ Go to **LINE187** and replace it with: Motivation ~~~~~~~~~~ -From the OpenFPGA root directory run the command +From the OpenFPGA root directory, run the command: .. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs -Running this command should fail and produce these errors: +Running this command should fail and produce the following errors: .. code-block:: bash @@ -58,13 +58,13 @@ Running this command should fail and produce these errors: ERROR - Current working directory : /research/ece/lnis/USERS/leaptrot/OpenFPGA/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/run019/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH ERROR - Failed to run iverilog_verification task ERROR - Exiting . . . . . . -This error log can be found by running the following command from the root directory: +This error log can also be found by running the following command from the root directory: .. code-block:: bash cat openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/00_and2_MIN_ROUTE_CHAN_WIDTH_out.log -This command failed during the verification step because the path to the module definition for **ADDF** is missing. In our architecture file, user-defined verilog modules are those ```` with the key term `verilog_netlist`. The ``user_defined_template.v`` file provides a module template for incorporating Hard IPs with no external library into the architecture. +This command failed during the verification step because the path to the module definition for **ADDF** is missing. In our architecture file, user-defined verilog modules are those ```` with the key term `verilog_netlist`. The ``user_defined_template.v`` file provides a module template for incorporating Hard IPs without external library into the architecture. Fixing the Error ~~~~~~~~~~~~~~~~ @@ -80,6 +80,8 @@ Now we can return to the root directory and run this command again: .. code-block:: bash python3 openfpga_flow/scripts_run_fpga_task.py fpga_verilog/adder/hard_adder --debug --show_thread_logs + +The task should now complete without any errors. Fixing the Error with user_defined_template.v ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -89,7 +91,7 @@ The `user_defined_template.v`_ file can be found starting from the root director vi openfpga_flow/tasks/fpga_verilog/adder/hard_adder/latest/k6_frac_N10_tileable_adder_chain_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/sub_module/user_defined_template.v -.. note:: This file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. The file is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. This file can be included in simulation only if there are modifications to the file. +.. note:: The ``user_defined_template.v`` file contains user-defined verilog modules that are found in the openfpga_cell_library with ports declaration (compatible with other netlists that are auto-generated by OpenFPGA) but without functionality. ``user_defined_template.v`` is used as a reference for engineers to check what is the port sequence required by top-level verilog netlists. ``user_defined_template.v`` can be included in simulation only if there are modifications to the ``user_defined_template.v``. To implement our own **ADDF** module, we need to remove all other module definitions (they are already defined elsewhere and will cause an error if left in). Replace the ``user_defined_template.v`` file with the following: From 269776bb9c8d05ce28d654dba9efafdeb5b81f40 Mon Sep 17 00:00:00 2001 From: bbleaptrot <35536624+bbleaptrot@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:09:23 -0600 Subject: [PATCH 080/352] Add Waveforms from GTKWave Upload a variety of different formats for the waveforms to find which one looks the best for the Cell Libraries tutorial page --- .../figures/Control_Waveforms.pdf | Bin 0 -> 4435 bytes .../arch_modeling/figures/Control_Waves.png | Bin 0 -> 106733 bytes .../figures/Custom_Waveforms.pdf | 100 ++++++++++++++++++ .../arch_modeling/figures/Custom_Waves.png | Bin 0 -> 102893 bytes 4 files changed, 100 insertions(+) create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waveforms.pdf create mode 100644 docs/source/tutorials/arch_modeling/figures/Control_Waves.png create mode 100644 docs/source/tutorials/arch_modeling/figures/Custom_Waveforms.pdf create mode 100644 docs/source/tutorials/arch_modeling/figures/Custom_Waves.png diff --git a/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.pdf b/docs/source/tutorials/arch_modeling/figures/Control_Waveforms.pdf new file mode 100644 index 0000000000000000000000000000000000000000..02dbe1e62b647fad02d2e44881c780c765d48884 GIT binary patch literal 4435 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%0DK?Jip$X`e!CM;ndd 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