From 00848e096b408a43786ea283d4e77d32189994b9 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Mon, 25 Nov 2019 08:38:23 +0100 Subject: [PATCH] Hitag fixes (#887) * don't display error message during 'lf search' when no Hitag tag is present * remove superfluous options in 'lf hitag read' * fix setting of default threshold when selecting FPGA_CMD_SET_EDGE_DETECT_THRESHOLD major mode * some refactoring --- armsrc/fpgaloader.h | 6 ++--- client/cmdlf.c | 10 +++---- client/cmdlfhitag.c | 37 ++++++++------------------ client/cmdlfhitag.h | 4 +++ fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.v | 59 ++++++++++++++++++++++++++++------------- fpga/min_max_tracker.v | 6 ++--- 7 files changed, 66 insertions(+), 56 deletions(-) diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 09eaec42..9746638d 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -39,7 +39,8 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_CMD_SET_CONFREG (1<<12) // LF #define FPGA_CMD_SET_DIVISOR (2<<12) -#define FPGA_CMD_SET_USER_BYTE1 (3<<12) +#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD (3<<12) + // HF #define FPGA_CMD_TRACE_ENABLE (2<<12) @@ -61,9 +62,8 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_LF_ADC_READER_FIELD (1<<0) // Options for LF_EDGE_DETECT -#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 #define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) -#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) +#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (2<<0) // Options for the HF reader #define FPGA_HF_READER_MODE_RECEIVE_IQ (0<<0) diff --git a/client/cmdlf.c b/client/cmdlf.c index f661e518..61040f04 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -943,12 +943,12 @@ int CmdLFfind(const char *Cmd) PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n"); return 1; } - ans=CmdLFHitagReader("26"); // 26 = RHT2F_UID_ONLY - if (ans==0) { + if (getHitagUid(NULL, true)) { + PrintAndLog("\nValid Hitag2 tag Found!"); return 1; - } - ans=CmdCOTAGRead(""); - if (ans>0) { + } + ans = CmdCOTAGRead(""); + if (ans > 0) { PrintAndLog("\nValid COTAG ID Found!"); return 1; } diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index be807222..22050a2f 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -70,7 +70,7 @@ static int CmdLFHitagList(const char *Cmd) { for (;;) { - if(i > traceLen) { break; } + if(i >= traceLen) { break; } bool isResponse; int timestamp = *((uint32_t *)(got+i)); @@ -208,7 +208,7 @@ static int CmdLFHitagSim(const char *Cmd) { } -static bool getHitagUid(uint32_t *uid) { +bool getHitagUid(uint32_t *uid, bool quiet) { // ToDo: this is for Hitag2 only (??) UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY}}; @@ -217,12 +217,12 @@ static bool getHitagUid(uint32_t *uid) { UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + if (!quiet) PrintAndLogEx(WARNING, "timeout while waiting for reply."); return false; } if (resp.arg[0] == false) { - PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID"); + if (!quiet) PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID"); return false; } @@ -246,7 +246,7 @@ static int CmdLFHitagInfo(const char *Cmd) { // read UID uint32_t uid = 0; - if (getHitagUid(&uid) == false) + if (getHitagUid(&uid, false) == false) return 1; PrintAndLogEx(SUCCESS, "UID: %08X", uid); @@ -271,32 +271,19 @@ int CmdLFHitagReader(const char *Cmd) { hitag_function htf = param_get32ex(Cmd, 0, 0, 10); switch (htf) { - case 01: { //RHTSF_CHALLENGE + case RHTSF_CHALLENGE: { c = (UsbCommand){ CMD_READ_HITAG_S }; num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4); c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode } break; - case 02: { //RHTSF_KEY + case RHTSF_KEY: { c = (UsbCommand){ CMD_READ_HITAG_S }; num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode } break; - case 03: { //RHTSF_CHALLENGE BLOCK - c = (UsbCommand){ CMD_READ_HITAG_S_BLK }; - num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); - num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4); - c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage - c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode - } break; - case 04: { //RHTSF_KEY BLOCK - c = (UsbCommand){ CMD_READ_HITAG_S_BLK }; - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); - c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage - c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode - } break; case RHT2F_PASSWORD: { num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password); } break; @@ -322,8 +309,6 @@ int CmdLFHitagReader(const char *Cmd) { PrintAndLog(" HitagS (0*):"); PrintAndLog(" 01 (Challenge) read all pages from a Hitag S tag"); PrintAndLog(" 02 (set to 0 if no authentication is needed) read all pages from a Hitag S tag"); - PrintAndLog(" 03 (Challenge) read all blocks from a Hitag S tag"); - PrintAndLog(" 04 (set to 0 if no authentication is needed) read all blocks from a Hitag S tag"); PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)"); PrintAndLog(" Hitag1 (1*):"); PrintAndLog(" (not yet implemented)"); @@ -356,11 +341,11 @@ int CmdLFHitagReader(const char *Cmd) { return 1; } - uint32_t id = bytes_to_num(resp.d.asBytes,4); + uint32_t id = bytes_to_num(resp.d.asBytes, 4); - if (htf == RHT2F_UID_ONLY){ - PrintAndLog("Valid Hitag2 tag found - UID: %08x",id); - } else { + PrintAndLog("Valid Hitag2 tag found - UID: %08x", id); + if (htf != RHT2F_UID_ONLY) { + PrintAndLogEx(SUCCESS, "Dumping tag memory..."); char filename[256]; FILE* pf = NULL; diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index 062ed484..ca30101f 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -11,7 +11,11 @@ #ifndef CMDLFHITAG_H__ #define CMDLFHITAG_H__ +#include +#include + extern int CmdLFHitag(const char *Cmd); extern int CmdLFHitagReader(const char *Cmd); +extern bool getHitagUid(uint32_t *uid, bool quiet); #endif diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index 96d27372235d318496a4516302af82028ad6b659..b140b59d767d9c7cd45225326aa1cd7bda79af67 100644 GIT binary patch literal 42175 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 Oa`e?e1@!Qk2x>FgZ|Lj2H;=R}>i=V$Y; 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 a_^$9HzkOAf3jBLqb%1~OSJF~`%l{7?SUBPU literal 42175 zcmeIbeRy2ebvL@sIU{j2GtwN(HdTqCM}5w{NpG5?Ejp4-QG)l;#e`Nu0!K2istW&toBo3?iPmG&QM91|p~+4i(@M ze}UiM+UH}=NG9#QFMsrTZj|Q<%SYSi?60+c>$le0+fnClxx;{0PV4H}PYmq-XhCJ8Q!8L(6%hrZCc#EWA!?e){IzOZ#ZC6C2QyE#shuw9bnmZzvd3<|$f`Wzd^q$ zTvd*zj0@=B_{losbzQBgd12Tlm@qO0W0H3-K^U#gaw8G4hja*rQQ5=y+`a0!>$S6@ zUq`e52t_jo^rPZI2#H(t*F8H%fexObjrdh`KtIBx7{huwu6|_${c4<`uTc8=Xa*ay z=%n?iof~)8eJ5y!`Vs*1Od1B+h)s=~Zn8BR4BE2>a~XL#)?Jyj~O=(aXZ(_sE)=ZHiDv z)uw>mE4YnGakZ4O3~VN^>COzyAa<_Qi+YE<76E?Q`j4;{ZO)xmZJaloFf%>-ef{$AYpn+X<_W#g-YXXu7WV0; z`=fXa8kdQ2Wn*f+9C#NcSHA-M+HM>wJS#eQ zT9PzQjRL~wb+x7eeu>;s`uog%PHG^!fVR*=X*znNYkxxcb&56)Hn){U)u1IUU*oyV|ino;Pytw?g>!ip}^H%QrGwB?nS@ z-JXSClkx|^ue!XxS3E{7J!Yxrc6TkR@hfFBAkL!)saXKX^mE~ty@Kk=C`3*WJhG>Z zzt#GAenR-Au;ALn;rk(^x~_%6f7RWq0e+R{PMX~3`n<7>4$@MAan+s^zmkk!HvCRo zrew6i9s3OYvW02stu#osi008})t@F0zdjV;`_`OlDn8#Eud}YGvrQ&qdnj2($Exv*z_un>$pONR6WVTS zm1vXH)Vh24C1NtC@I8+qm)ZUZY}#u4N+s^V5}dHQtoSgN;3O@#uohMoezk5X1HVqn z&auP;5Z+UZ6063qeBvI^u2b0#Y8Zxa+FYJj@3DC;6n@!l&ZhlQEQ+0U`ifMb{Z0q> zry9Q~X6SKxKosbLj4sdyM(?pZSGfA+@vm&`HJyR1Ictt9AZsqH*)RjY#uFCa^QOqi zhK#Y6-bxjnM8;@z^((+HmsfT>*EvR!-lgscHe?lkbr#YqV!Q#abkr6-NxKDvMecg} z_yxC+6~Ea5?K(=2Q?pz%0Nly)*nRvmH=xgZoW(E4HZ;Dd?UM_cMONe2nAw3o?~$#e zSX}V0?0Sk7qu0Co<>FU&A^wJuqW9=330HQ?Iwe-J5XLV76DJM$>S86k=-^*;9zWSi z8SanAzi!&H4esTe7!J()BwdjQkbOO-yWdjyCEEI9cjv$_1Y-ewztE_Gu0r)z!v^7&USNKNX~*VZwY`6loyW;KNH>tT31F~;0eb_e(ugem<>N|4d! z>X(aOpj{<&70U$7HI7AIOM|Cu9SZTUcNwipfC(k=xZb6XRa;823VxaUDM=%MEeP8w z_t(`>UMQ9VouQw^v zA7|Ktd%*MjDxH)ov*`Rx{6bgFld|h3{OVumq_cbgLKwg7E*&e#&dG8DY`sKNw42v7 zgkO)3wijbJfqy-ewPjzSaf;rEBxP)>3csv$Ikp^j192NCnt^bC*>+-=eYqOHMq{8k zFgscJWBO6;+X5SVpmqj+#Wol(f{0yKZh#Q^SGlANJ2n%)By0<47wgV37)A(rpMNoa z{YonDy$izSW#AV_sD6jvL#}=?em#hdlh~Gt@ax*U(|6Nef}k#7G0C9@2)O0 zeu2@K)NoE_R*tb?o?(Ky1FNI-i}@F`$hfjC`K3-`V5rjth2usDzxInZ-hRi-A|)M| z!Cf>Z+YX>VA^h5JwMAjNk3qja&23;jQvfp7L7{Xxg5eOt2*3io2TNJhH^Z_5$S90o z9L+F!El$vGtVK(j;~Nh2D}-NX^sDGR0rL)Qa$p9}V5|_F3Vyvs6BrjFIasE_?gR0Y zb35>4sU05=;}@XTiyz8%hT6ZSO)^;qkOlZvCP|2IFn%#-#6H{^$x&7!=oG>)yk{h~ z+vBIvqCRZj0shsOui)3Dc$T{C#Ab|(iE~5IXx0xFR@KO?>Xt09hhSS~x0M)Ewyw*<7Ud_u zr6-)BnfyzcO6t04ao)H@z<3I_Eg}5U+SbLquwlQM@7V!E%@M_(Abz;ajhIaX+J1ly zS(n%O$#o(YiXSrDQjs^{mzKWPEa~@Hc#>T+JAPPp`#e%F4V(3gS0@}lOsO6+J?Xmk zysblHEO4Jg_yzBapP)@`_o~f#1`ZWt{7fi*2y?+`Ri;M?zMpI?nENAbv}s2C@L~~j z!-j|-T8cBOQH)mb>j7%vkse3fxNQ~MJZ?QE+q1DF`qN?lwfuUwKj>-$<{9|al}&65 z;)mJ}e-!95bqcJ-q;--Scobp$qAM-T#xzW0mj--SoLa*ZKYj@PdYFJ#Dt>6T7i~9? z*ftm|^gQG0h0DLxj)H3h?-`*OceBCo_2P#v|6&Nx6-DatV{P6DxXjM$yH^gfJdpK>pMyJYMWAMzqZvnrY z)3(Zt@NkeunO^z|ofO!s_hI)2_yyZiPMm^mfl2ADpLW+v!ty)4s*T6LBC(Oim+XfH z`cu?@NsshhB4R(N#1Da1Y%>ecF9;=2Dh>{_4r2ETwyPfh5;3cBoY$0686IHGO)_Q& z@xu!LQg)ucKkX_S`#+A+&+qa07i*liwG{ZeKo;5va4T; zf9c7-O%Ld4u}QSaR58hufI#AY-OGOotTvbA;Uw*mk?nTuv7VRpL2COOfK&*-VOmq3z>WQR~w0 zDm8zx@6VH6(JjU1No>*g#O-o%wl0+aGHKMxi1;!iPEXnyN;Dhe;sABZ`cVGsUiua6 zO~SdfL}%)4Wpe>U>1Pw)69kVkUmqW7P zq?YLi?7W1B7Q(L)8l}B=o2|yBH0pG0kC%a8cT!tE9?E}};a^;7wT~Ka>Svk&WVg3q zLt5Q>b^Z%ctk1`{wOk@k<~sVZOc8OAy0Ymi{JKLV*PGj-AEws|_PU+tM=#Ouptb>% zb;shp(WJG~U3K@1ksmi+Mvqx7V&rb%*Im?p4M6H?U%&WCi@=k4^nDH+0^{`CfM_Ys zCGl%i{%c%AG@~#Vu%#^}*k>E@u}+GI@hi&a{R@muFVUkSQEE{}M#T?n)n09?IZg)% zG{>47p@WeOLqID%hc(3jL->U#I#jE}j$$ZFGOuT&K^|??Ru~ z^g|egB8_lP!TlEEhj+=AkD8^%YM?(1_W(-4?{sc|8Y7{)JH2|ezt&X^O?J$8J;m==uhAYx(s(vtbU z*2XC10Ax@r*t$r29zqp<*^}nw$$A~&qODaQ{_(xc9G#n>@=8!7`QPz4g% z8w~L4Mf%b3(&qR<<8bZR@RC-%@O+gBLq4T~UncZx%>3izQL&MlUqm-7+Su4G08#;d z{f*ctn$g4DQG27+;+V%l#E=LZL*oFyCJ44=MJld8Nm42zRwsu_>1EMwecZLH96vlT zQq08bjhAWsrcB0+V=yqDCD!+Vf9a<*3}>%#jQ+{)a@rp>CfA-ex|~B*@xuvPI*Czq zW)Fd2Zk{$)nupBpp7?Z&hhH+XmLq|7->|Ne986*l>g_fdhn6aa@e2XYlKDU`ZGO*A zj++naDY=Q#cbdhX5Pl&7%$8q|V_Yo6X^8i8#@8>7A41<%gz}k{PY=FZP;1feWC+Tj?fQmjQmkyBIT9^dv+01!#-qbFDULmjJ$_egjYX zcKZAa^&3t9L|BU*T65EnX_;7DG^RB0CMWG60vzDi6O6*87-*OBH<0!^OIM91rnTz$ zq0_L#SV+IfbWJo&8{Y+Cfdlhn@Hm?{w2B{ce=PmH-Vq5PJFBPApY~C6f3!M&=)fDi zoe;jUqAM^!jH?`#dUgD;96P9gU2c@kWpjo8A=)>bE}Nf2W5M52`7iy?#~PNzHrp@L z3i-QBVk3k?j`82sV%71(1HW_NBLmz1&AOr&3wJ_;*Hqf_(hUCP{7w;O@E`#Yr;VNF zY5I%jZ!VoTBYyZH5pAN|wPx8jkmKC(RgO7OJ0pG=-H^P9{!)IfT=%CsbH+cM`sk;k z1K51r=Xnz*Q|UDXmC4ub)Z8`I($2yzy()gl{418K{i#@)UtBP@F%cWAKNbte53w^7 z&gyB<|KHMK;$ET?w9;xo?vFD3EjNC+QovMxi(b=KiUzisFHq-AH-FvGU0qi3L;a6L z%(|wQIQ3)R)A)+KBhq%gnU99^Uy-&|Yx4SW@qM~fTyT&6EhL_l4WAi5Ea{zd@6uXC zQ)6xtFHEm%vT8%|L-bICH&{Se>`H3L!9P60_*E0D#1Fwry2N$X+_A`;fBjj||iYEv-A(Df)cJSn75w6nV(jk#zlQJ=v4taV~8KLybH@xuu7FZR`=Ch)7k z_{C4!x7W*PlvkZ7l>d?>X(zizap+gu3D`O>erRi6{%Z;lu!Syl%z(6Lb5I=PJS5{x}>5X(B^RJ@<@k1vy9gZLJlUP>&6b)M~ z66*!>XdxglfZo_VcE5gO)5W<}_RzR}Yn_d$+ymYX1JYE%FV*K=#%E|#U&r-}3oTR7 z_dk>M`@gp+z%M-Ma<&v!@3N4Kl+Yc-80kwgQ5>q~UrwTIbkd>1Qn6qFgax)Gvw1@} ze#q8%lZ{N3eA$-uD0r|RiL_hh1C{vU%_v=f%`Eg}k!wpjg2UbTTY2LAS3i#{sNX2m zrfGz>H#b>PUQ>l%o_=xt#v{BIg;-jDmUcTSuCL=!#HT?K)O&*bR~G#1xZwq+&}V{S zoH|cofup@czm(mr^#_ex#hLul*7QMpIS_3r$9p~gC9N?z*lMF#!^p}JyI>+f+A0~y zP?6~IuaTND`#v*G-yvOCigxMxSY{|%h(S3Ck!xA4D&A_tdn>i_;rS!aN5VWeDS=q^d*N4K4p0h zQGY02197jvZ)m+ZXmvOUAh+Ip+I70}K7Ij?OWUWx{@Nm&8O! zXd&q@-M;gtWYf-Jx`fxl!MOIj>t$=_)5d)BiKcbYuhF;i-?YU?=^KLMhejy>6`_~R zWmKP>Tc%%7ks?JSE`VPSB8ppG{X+grKTA)HV-$ZbeinHG!&!Z%AM1r+bp^keZFL;@ zSaG$&FD;(=c&iD&#YwC%KJV%m=fAeV#PuQnrEkHhusiqY=_?HPHmT~JhwDj)y z3A2ArwF4DuOh^Sr*od%_$F1fkF^J?4?0_ z`?}OU`XvPa=cCbk^hkv5vx;36$v@d$4}!)C(Ejv^uoZl8nr;qk(|i@UE)T>ri2x4)Z$aCqo= zLD_krL#@&;=3fVCxoFD+0uTm2uqy-ndXC3cs_-udYHlNJ*kddFLi{ij8KE|gC|2qZ zwQokgFIM(9Jgy{f-pFJIHX^~sy0H?AOlxLv@XHycKcfzgQ! z_^D%L;FG8|4fxkWirV@%z}7-N=_Cv0PO->CG;9&U>y@hcU43p}?!cw{uWiuhQluPv zl)hkl`W5i6Cc202qlLY?h4^Z_9&>W*?0r=4Ac7b0uM6OQFG1Wd)}cQyAGF*1VxOcx zkr$Q`S*q|a{TI-bwxY2M0&GGN&WUFe0{(T1CI-R3#{c&YYvT5$Ht=gH9UAU_B^*Dz zM+a;<=Cr;5{HtXY!ZPMo+@FAd-AfzI`?;b6I%tBd-J&;TzfFq|piRKPu|wyaUZKL$EFN)0OyPmPQ2JcnNP1ev}3GDP^i6jbep=)yPd| zvXokOeSLoDCVM=(T;JK`w{h3hj1WoeXSgD+fN?4Q<-l%u`bG7E)k=%Y)nqwPGzj2d z5hR0(75>F+>nf)m{EH2vlbDWqh1nJUrJZ4RjAd#$tRIp~o{7H|>m0dDTWZHjM#jY* zu0Pxa{*~ggjZJ{I=zhJEfz<|n*)A50)Eq;f;pLLc79=JoCU?9xQ&3DbKTckEFZsGY5z!a zuen1{(5CUrkDIp|U!uPsNv@A|4&LgnMY-lW0bV(L!KM1zx%ZE?PHP!7*0OdswtzPH z_;nFIAzMCczHq^0*MDi zQ6w5yUypU>v7>(eI9;VB`kRZ9Utw!C+~NkSQFB|tFAf)X6gC%I*3y%->}dP}Bkdfb zjw!_Js`%G^f|DeXZ_|Afz^}Odk91ki%<5ZRpUt7K(WA1Zj8e(}W^K$ZoC2@>2Jq`X zkjGl~Kk(BxZ;bZhbU+=P=g9rs`3&-~e_d)FHCN(2YE7r+f7gDCP;J<1tfyyarEDk| zI{{=J`CYHa9(KRgM?fp;)*3jDeS#Y4qtaMqDO)$(9KtUyCs6#0fh=wr7t_I!4kyuA z#lJ{ZYt$mlTj)>afjcjV?=pUc`4_dUij^Ao3Sb;^WctN)hn396?rE&>ufk*0EMl-f zcu!WC7IPVq5;05H=kU-ueke}>wot!OBp49rSBp)f5E8P&zmB8SWV1+Et5tZdA1R4f z3SScNNh%-{0?O@@2{xxSW-IZw|0*4HcK4@2 zyCOfPqS%}_c31~RvA@l#)Nc&uIP=($=W#Kww7@Ihggpdn3-GH5*AcW7B}T~7EBqo@ z+TFBvBXxC50a#>%1dj4%bDX9!@C3v1wHG+zLaA!&1taI5RPC~)f zN!yVD|Kj}D6I#oGrs=O`=HEjXQ=QOnu)i-50iMR2)q8fDjkH%Tv>Voe(f?2`Db#N; zE~2O9lAnWrEpqiMs6Q;gT$E^;Kpu7y8rON`3mKn(QO!H_uI$d%PtASNd@;8ac3xje z*Gc&E>x`g&W1D!077v^Kxf0z*&Ga#0+#vr!T;{B~wZgydLAI;Cr*1%>&VG%WrMUq$ z|F=`~SZq4!@h^KG&sREUMsgE2mQvJ_K1unJ*0*9yqNb}~J5_yeXTE;ec#e3z;$-Zi zXA2!i5<6o7|8k?dD1j(PPw8E9OHunQy(_Bm>jXkoOJy8ZJ@Opy=R09npD8Szz7F+% zy-Jq{aX#e%+Ad5xnl|qoOqT15`iE)rf$h#3)aeO}*Gtx<#UmD~4GY(RTUp6ob69VO z!B0AC_V?KCS}=ZbJrY!pu%-pMFa!RT!{Wwxukve%B}T1uqfy%=^&VTs{_mp_}4D<`4R_y?=iSxpj`#b z4~$F||5EnZNf)ulU>F^wl~>ad2V_6Yzf2ta;^C*q60oX>x~Rg2DR#x8TTA3~<;{8t}F z@g|RJPWM=%Y@F%y##O4#a-ZG$`Od>wcW-_mn58TxD#(9%^@pX@fPR!7f}d40PEo?J8#Fnqa;Qs<12oNpcUpJv7 zW6@_}jkz`>*%!N4|2FR*0sJbH(l7V?S5iQC&_-_0Vkwz_E#fv$`}!532hyo)qn18~ zHnxa00lzlEfB?Td|4^O(^2-hx$N*a@1QJ*BC<6ZF+KuaA=OZU0u=9t9o-fSgU))Aj z%c~m2Rhvu37wMl>{YHg0f^KrQF`(-0ba&ATHW zXB^=5QuT-WCEnQCnau00$vaeiOE~|IA0C*WTkEnKuS%4x61sePyUa&m?BWjiUM_yPY?`c+nY z47BSlILQsLhbi7;0srFoA>1e4&-+lqXHG{igs-LcbHKkYqPHcg<=y&2)NiaeR_ag5 zE2{aIicmpQ*d}z!L>2?&!!>vk@Gq{`VA$fYq3nhkq`&CQy#e9md?R|J=H>*KOnLSDbC8NCo2} zY;4bFdiv$o&%;f{xFX6FfUv*;R(*C155LZEgi|Oxua4UYV;WXU^?9mR?Rh@`bw*yv z>wXc94RoM7~$oyQcBl~?H3pOH( zRkuP9@vpaOh0|amYU;HOXJjC`fNs;8oizhV6dw1tjHkYs3*(o(6!jZ8DZsP~ z`1K+Xt@#)n#VY*5ald7Hy*@OeVCxy$quad7;rc^bxjS7jE|otjbTDikfpOR^v4U0j zg{bxDrPGr4>J}KiUbSh-sN!FWFYhovXDQBFbNt7{z8%umwberi_I67oaxs1yNVhzerz|s?SfW*+_viy7~qDGJjzI zff&KKK-N@P6(G(QDa60fAKA4E{ke%=IPA?cpTAJ~FQxA(Z3o&cSNIiSBE~=_6{1-c z{>AvUkK#}Wno#ot`@{7uYh{IhrJ!H71pkT>;Fw`+O0tluI{#ISNS$M7!m}Gs!)Z@D z&`K}=#r*40Y6fh%B@j+*0DBd9!8)bRGhUi=kf( ztPn=3;)jpAdu#=0mx8u`P;G!{A^bw9Lz)ZWJ|Ps0sbrhUW6y-^H{d=M;yaB99Tck1 zT=U=Uz;1-_>xBOJHGh{Mn#!UWn8!7#z-~)8eh8bnRHk1tmJx>y85AV503cexziy_Y zW@r1F^o0_EG6%jN>hvI(#b||p@y;9rexf?fAr+6~$#s*Qpp=O?O8DJWaZY@qiZCUl&5QWI4o)t_-Kt!BQ><%5g38&mMZq4+cS7kbF!LV+a&#BJ|) zH=D=5%GyQ5CFm~yx_e<65b#rg!eR!6ahDhP=a;eTCd6BmIS9d_pKI`%fCV~FPjG&@ zVH!bQj0?*&m+Ml##OqZ$FUxKG^UG>}-Xaj^Oe|@58^Fu0kE{Cu+MRkb9XLMU{V7h z^ZY~q{*8K&o&X99p=gf5`7d~kdE@0;r90bd)M+n& zTuZa*Bd{%X?zsH=L&R726LO>AU+N&(A_!ES|LUvZt_J*zg~qYkLAsgyd^o@_j&ES> zfNX}XC{F@oH@N4kE*CD~{4#j1-yeo8^e4!F**vcG8t@A}yv|*V&Veudm4U;~Zl8bZ z?jKdZVWV0sm>-Ga=y5|iCn5gz_(+>v#Qf`Fx-_3EBcI{{*)#klzkY-DD>;GA+j%TX znuh3RHs;T`x>K0L{A;nZ2>aREXQiZhq^DDQ`6f@lb`t70 z{|^STXLO6dWx97+j3tU1j7%2W&o(9oPix91c=(0-jmWR$S6~lU1Gbz!<%T0hSL$s3 zOOpVylIzd&`LBH_DP;W;|4NsQng2y!F#Ibk%)czUmsQUJS~0XWiztdcBKznM9e}T= zUtGTd|Ji|soS^T~j;xu2^Y7V~BasaE**(7uHD?=j7W&n2CqVoW>Y4&b{lc}Gc@#yR z79Iq^=s~}XV?vQNHhNipkL2@TjC#|snRw5b5`Ko*9Bj*hUYpwt)6Imkc_)SZAU&cN z$|ehbZmYt-aQ@4Isbttn_8@-9$sh$}Wm0+p{L(-tv8EUo6EP%}j@7bHf;AnD@TW*3 zes}_3j~7>~aY@+cGrDKT9Cy9Ae#4_D%HT_s0X$0o>VmJAt7ZOmmL719jT`SEZVVvX zU@Rv@6tnS@Mu>ksB9hZ6r<|glvdxZ;=--MwQA(CaR)ROFc~T=219cTUeBv5-*^T15dK`Rs8F;`LGk;ffamBAVE_wTC;DXkOS-P^Dp4n z6L#}h{Z9Q@B-*cknl7Zp))O*0j`O)0*VcLQ!&0BA_v%|kYu~~q{XE(uZKSJvR=Dfs zo?rfEx$bkhQ`+B*e7I0Ih4|qF|JrB|Mf%xx|7wLkXBYo)D*#q z71o`OQ2a38JZVnlcGE7|Zb!#!FS7R)6@F!18^!nqlY)KNxS8&sqt5g-uz%PaD^}MZ z?v}u`o%Fiw$~Wwoy8?k<#;;lRhf*8RKPA4>c=6b#pPL(m!mq6u1AbKfVFCHCdxqGY zDg(O%gk^VjZN4i1<#4pHXN(53_B!)?y++>A2L-9-UuLpTneMyjGs5H?&|eKEdzpiT z@GE8i0Z#rNx9*B4BF6O_hYxhxV-$hb+Sj{m(RbD|8h_80ZP1a@sr&mff^6j9^(Eez!uZ49>5mozodSG_CuH% zKTL^elfFZ{i!K#S{rd9?(L(q&X9w2Hqg~tvV?Q1NkY#~imHG`}lj6CNha+C@;?&h~dMwBnrlqsp5x0 z{UNbEl-&iO-s9p&^76u#DV!%dn}=aMV^|gZLP+pHY@l($^WQX^dt?0ovVEDwPW|lq z!!PRh;@XXiS@oU=qW$5RIe>j=bDwR6U$E*;we_-4uv4*G{UGa?^V`K)^@okduH3k@ zyeV;~F(uIFDb(quTwTWbFRUrfFXs){`G<*n70$mxv{3vIqY#M`b2~X~C=w;3OCruT z0Q~Y|XzKjeSlj1f+w@(Qax-j{H$1|5qM}}KeF@~hc#macTN~r#x*}23Z0A()D#X8v zZe)8iQnYXj^B|aeB=MT&T>Wz6hwx5|CDSJ+QAWC73})#5jSD zj2O2G#SfW(!MiwP<2sQ7j^yC{G8}t6nReHU7k8Iajeaqc^5KP}r64*2||D_Oi z0`%VoJp;8bP>TCpmH%R-zJwuryB*u9?;>2uh$nviq0hfCu45Qi$Iir}xoy~_k2rV| zI{)SIFP!5boYzC1NdDut%XwTg_*Y`LF_FaiuX*uZsLkR?vU-o&KVJR(0et;keT&#` z*AMHOxN^LO*Q+Z3g>fy@QH;0MUV%#BJFPu}%0>o8M$L0pbNN?nL+y*7-k5J`t^1sQ z5$%=DxYPptOYmN0{Nih))cuD~Qbxu#ViqxD8)wk+L}>HtOn^&%Y9~r7Xvr zx$eub=@c?zZ8P#;z%Q4lD789H@8bTbdSFxS0MGL_@TMPwx!_5!bvG>&^_I~~2o7iC zGtPgtX@D&|!u9hIGKzntLiw+wD4SpG)b;B(K)6^a;ciOzo7`vhEzW=8q#L6-#}8Y2 zO#~9{JIp`gCn5ZLf%{{%Abv>8`|IyDK0+@ziunfhhc5r}#)U=sx`FesmKteLzfq8! z4OGWPkI5@h0H*Jz@urS=7{BUZ;t(GzKnrp#*!rUUm!10y;ry3iD?zC&U`q+4OB%we z!)^rmFN<(Qk<4u4QQsfyq}v8BmH>qSzZz*$UST8cb(n?bc;DQu*xHxbK%$`jkYk>m znzAh(J>knARuZ06_!r^!*8;5HJM`Qj4#utnr#zcePb%?4+Pi9T9$!Bq_FiS=Tr#bkEm6FXuWo!*R_VTzUbVcBcbGKSpoSTGn1nw6-)z8aq zyas!yT#;kor---~D(Ao8XJZ=~U(HS0|JCi!84!7J#=ouHA0?<*u&<9b=|9BoQsZLq z#n=~B@?Tv0bYmg59$~|;N(BKg(zkQXlhO75`IJ7B;PNT78lxwvlVNLu4$$r~^runh zE+c;U07@W!Cz3c|91)eg9_PQx75q8?I)MG$1lr}fSZZ8l5X^voY`rKpjx^))5ExIJ`_nh?85(rb*nZdK1RN>{YIV%K zLl&@J(Z-0<3yvTDs0d9dfPbMs3|mtsUxc`;Y^-#@h5AGNgut<7r*Qxa2OyIM2NIPK z;MXx;CXQLXst#2t<9Se1ydcPb^^zA28^e;eqo;7u6liTBp1?ON8$UUaQl#t zU#{?7#;?TTO+NpsL1>Y>RweRtTTLc4TNvy>#P|lMO8yJ`5LSy}%M)JCjTE-0M#jVE zzp#`7uKqosU8>K|+qap`eP(|s|Ais93ygiQ=FJa`r-UcdU#UMte@6Mt8jhu$OnRMn zi6Q)XrC%!lWp{n_y005I%|qua18fh~9~M{#DFKsWpAgfr?nS=FDd5+ha=Hq?)D|sb2|WB#_is2A{GuAZy(Sw>F*jpm!}J^9fMA2=)5CUh z#N4ggC>uTot+d(cvVHs_Y|-rku{b^g-0Hw?^dcE;6Z|nxzX|t@zoo*ztP$^?ibzFBwduIY zupCii=lG%2vxGhqNgfWtbOUouSmz4=!mR?Ij*Q%{H!}p7=8k0A+@xa?3O@f5^CxJ$ zub7&Mw-|(K##B6xK$#+#g)07)?`EoaMj(D@Uv~gq^~M$AUne3Ry-1(6&@&DKZrh9$ zrgJxHVJrBRrakLWzwwyfE;f~vuvmKM(K_6<;P_!twqiJqWO?I?*dUm^D3$o3xi5F| z4%~cu5#2W2Z1=5i>=@oGo9)p}hHB54>452tVz%LH-Ug2Cf zU>vo6RRe$i7UQVoLi)s11;4N}wYD;jkFo2By_)~bt2{qt;CmJSTI}rPvWSbo0;1U%MVNmbNSFG$bd`R6KDMl90)!5c?GC(0tvln_dxh@J z@yQ_-%iWQfG}goLbV)>R!}S|k4$IGdIdWnZ+qxldy&QPU>OCrc=ydca5VN9_4(PzP zxvheYXDrOWOz1`bnyt{CAB^DW?uF4ytaIeQM6w@9^ePG-+7LF(c{fUx^br600i%_L zC%CtV=}B;-l; zYQ!g0o?5~2WYh~JR^bSfjCU~kG3LJ`%VexB<$(#6=$ zeawWb( zP>+eNM^gKes8G7Kx_;xT=0klghY9yb*#NSi*k`Afl;iIWh3n__E>vhkcU=5h{gOPL z?K%?1FO*^DyIT_n5jNz1h66?h@k81D78sf1$7w)pA42IdMEzjEsSc_;Qo-GP0?kBT4KH`|~mI2q``Q8W?x0^&Nc6+Zt` z`7c|!2S2A1c_mEJS?8)L=9TW6a{Lfm6!#y_{bl5Ie^+VCUgKqn0dieRfL|(?RK_UI z*d8vwC=hUS;?v>!4a5em*k=7D+JA%{s^sf5q=R1+EBKXWS7eOu04$*Kcpgs#s#b7b8`5mB@eTUYh{FZpJ=T!wFp3a^w*0anit3AHNVkM7742>6SCNT7m^* z*7+|t-s|!&tQQYZMSxkT;1?pCZ3xnXGkSry==jtUZ<1HTjp$sLC=uWl2T@8e4 z{>7sReiaB$yY{f^-%okeC1Pcth*i!nqlYs%W2Mgnyf@tYd%qw)RH{9$%^G_czg$XX z&79}=jUR?OAHpx3=`)#s$(i$0#lPC}n+p1CX28EZA>dzY;iCJt&aBq2fPXC@kHQ4o zI1mE7GSj+~-Cgp>?gl!>UH{On-@rBIyNs9Ulv8aF zL->VpjWYjYm8r6IA^bwDK*ChQ&*XpGB4jh2Ugbl2_a6$RhoE1w+8+Ax!y1+U60!T3 zfAN_kHlCghFIVsjT0kSP6fX}6*$ zMOQL$n~{{$61)kxV?K-ec?e$p#UMez<}GyOgA3;hZBmkPlV`}~m;TBm40k}La*6z=LQ4ps0ACx6v!q^)OZ z!L{*aLvi_Jb7p+=-l5msf8W8aKSaJjAbyBIB1ON*g~yruo`=T0<@;>kphuk++vNIr z(5`~{XHmX?qj?H_F1!ArTYqRzH(jA8#1ODM%7-JEdzxH-sP_ES{O{0P`AmN8eXAGJ zsO%a+SR)n9A$|xxSivutxF^nUAB*AsL*9^bHJl2e(4h*y@UNw8Gg|F~g$|MaD`SVw z@x%BG{7Qb>E!&V-uWfw)hJcVqpDmtejvs=jtTGSxEbHgm49e@@M4KeH3Gizk+BAz) zKkA=vqx*!}I2tJorV7`NH0G-C3)@D5c8zm=Le3~~BFs$Z!u;z^>J*8LKBf%gb@{o+ zYfyiJPy=x&@U`xBMJ@6kPlqLHzI`0Ytl`f?r&1s3I_^-;l0AEgVtw_!r-Q z$km2mTM>k7aHnN|&pZqNhKPWbXw;N`F@AA;bwfVds^3A|LDr%w5yn6t;$H`4=by*( zb1#;-e@xvoNeA@h+#ipB;r>H9+1iyowAJ_*`=s5qp3g7q3aPDFRs9C$=l0dM7#AH@ z+?kt+PSE8%V?}O4cdFwpDWPY~JT=>9760OE=hd-goL?@-*BKYkPlhw)_`Biy`L}7m{IU&C z>TP=5NfhSdwjWwaiH9oruNMi?rZA04ytxRqQu;*@*17t{`1P#QIh}ZP^&vWapzBXz2GjH`EvNXj@p)gDmE|8t zt{?G31b%TYyG+xHkr@Tp8vJnm;aRi0KVE{X|D25!QVA)M7wG{jJ+Q`hza=9#GZOJW zEVIEEYYKX+i6n9v_SuWid-WS4bvGy#Hd_R-f>yc%z+e_@?J$1fJ%sn5euH9`x%pU^2&1Jh)a{J{EaaG z;#A!>{pDZJzfumg$zg}83UjOY*CGen^m8Aw1MCj*ueWKX18sU0cSKkF5>@pZ2!}pj zp_A{!zZ|48;cEpkVfTgA{Hq+x)2no)Q|(Js^RHvE3-nP3d*TL=E-=aPIO z%)fwEFa-|1Z9>Qx?nU&o>NlK3iO1z0#}39-!7rFfpdP!#T&Ni)V%7Z1F*(G5?*cvzc{`@ z?Yvi6NJz~Ws^W*VT&QtzcnupM;3=cNe%%DxrO=9vInrJns6Q9~y2P!q_l`CPZ36s4 zwFbY((#JHF_JUC1GD^SP_#vzW`V22pmDL4(p2@%1Cd?#aGx?WQ8BQ>+4}^cMv3f=; z`1Jz<|2k58T>N|dYny?R3??I?dH#RTzt}gkzjtR`4^|XzC$R?cJp5k>q-dm zFE7L-WYMnHuMq!IVT2QUK)V7V#J{|-;q||ce_{JUWm*&wtJ0ki|MJ3y?}+D6b{LLF zh4_~j);K~xd4K+eHXH-_x5#a7*?iFF5dZS%$vADDVKYPgOZ9ob@fzx*s_kKjf1!Mz!Pc?Xzr5>oh3?_>8akDTeMG!-?QeA zRfJ~x)G9o2mh`JeQrGYg{NP-2BsWWtw)-AQT9%sVe5#QU)+wRJ73TYGp6aW)Rr{3u zJ$wGR5b6+H>@r`m8JX%+f5!(~|HrLkl4E7gp zNX?J>0{$t$!T#b6=^FCK71usapK#`9YSy~K0EFKo;mpZIM6*9G5^(<`q>(4gF|928 z5BzzR*XF4#Qeio=C5o^rLQRfv4swRgdJ!Bmbqd<42ptjki7kkKu%;Qg z)}CudMt$MQ8k{7@lX;G9sWwmb)MN+O*`GA$=X_zPChM5?HRgQjkE>_qxG@u%K{XT7 zA6HK#JJ^K3H78dQmJQa~*YwQ^+GK0iX`iI4<$PE81O(hT-$S2}HNs!7T5Xl=&(3SA znJtj5y3FGuDQqU*O6WJ|>2o6Tqs>-d#BcM|HO7CD&u1@ds`rIBghBPh|JGC2)Z8-o zsqF7H&40S)7P)|h+t2f!__}lTHO4LSX!i1^`lkayyG0(!{z+54Gso@E)#3N37k=XD z$PyXn7dmrX{UUvqTII9>SL3An8lqb5M%k1-zp3VS2 zFX0}HD~;n1sh>zji<7#!FA%a3Q$6vUDE$%!QJ`NXYK2WuPrODo+7hvLVD7xgQ!Mne zP_u;k#9S-l`0r_{S%2WaWBeVC@ zbDHEe&2vUrh+Lz&!Z4mx-g9;ToEsunYx6~K|D1V|Pe2g9;D5_(cGn!WLp_L&&bM#t zYwn5Pkeg@U<~O0Jrb|(9tFeGV z;XDr=9KTIVQ{U6plHtuadP4lh7E3sdnc>aNeiQ0Gd)?W;KYRS_yR(I$&3{Bl|5I%F zlfNwPxtWF0=fXnp*Ozv#Jv8_2v57a8urw?LZLa)_-~HKF_D%lsBnw+FpSvW@WVE%j z1mQvxG>>NBGK__KA~b*=|CmmoHm9_IXZRx(4@J7~ z>DSJM%l>=(Z;431Hjl2RIkSZx_gj5bORJ=njWlVq1@|@72aK!22eR zTfa`fq}K*>xI$~7)zT`@61+L=CuqKiTL!9sW(kh>9)kBT;{C=vdTN$1>VIo>BzvGK zb4`5C&@4fEbEpZbGAFtR(5`_|FA`cG!!e_LPXc{gZNh06gzDLbA3y5GpmDH3FG^u*e1YWqnIWGc7mERovNK%_D?sx*xlk+kzin(nFh3E+%i8PyW%$WZki_Xhv6ZFSCEuK*7wX`vQ zGU_76Io}gWEtxQTg7=U=7=L*9dLzvnRP*Zf2mcAC*B30=ItTw8l-C=y@C|I`@8A_Y zZ`>rp;yHi(G5f#l?DVC|e=`!_=T%Q6Di3E!mxxQmj7PKnXkIjOzMS=R#)I1C^D%Fs zpYF3~&pQ0)*+S52_OF5`|7qJ)>2jdd|E?~(+8yjw49`_z)@5(g21*@_y-Jsfs*FR> z$lqF_%?2{(ZXnetv_-M0W;f?X=hS5;g{;)xZmsCD`}V3g1#Mgv{$uF!#*P_E9ke-z zE_-2>Ku^!5%l<_9?>UDq2TJ|xba}>m&ZW!vggd-on$IzD!321X&Y{bdzyAKZTxsJ< z=hEe%&9Bkrpv?y^1X?*;2);G@SHYA2v~7Zpy|0kLUHH7+GSu_Y_igl>U;JhUelr8V znStNTz;9;YH#6{?8TkM43@CpI4io$(an5PL2~{U_xvyShyIhzkLpk6gBg~S`G8*Z0qma-YFr=G{=s`3%+LR_ zUVKpd=YyJ`|CI0f0QS#s?9cn#LjKJMH9sHJ{$aEFpUM7wQ1kOa*&p=hH~95yw)Fp( q{gWX={$~2|3`zW#P_!%Re$6L>UwQ3oGC0N058d}1sHCO5mj4sde_><* diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index bb0795e8..ac329653 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -3,6 +3,26 @@ // iZsh , June 2014 //----------------------------------------------------------------------------- +// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h +// Note: the definitions here are without shifts + +// Commands: +`define FPGA_CMD_SET_CONFREG 1 +`define FPGA_CMD_SET_DIVISOR 2 +`define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD 3 + +// Major modes: +`define FPGA_MAJOR_MODE_LF_ADC 0 +`define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 +`define FPGA_MAJOR_MODE_LF_PASSTHRU 2 + +// Options for LF_ADC +`define FPGA_LF_ADC_READER_FIELD 1 + +// Options for LF_EDGE_DETECT +`define FPGA_LF_EDGE_DETECT_READER_FIELD 1 +`define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 2 + `include "lo_read.v" `include "lo_passthru.v" `include "lo_edge_detect.v" @@ -30,21 +50,23 @@ module fpga_lf( reg [15:0] shift_reg; reg [7:0] divisor; reg [8:0] conf_word; -reg [7:0] user_byte1; +reg [7:0] lf_ed_threshold; always @(posedge ncs) begin case (shift_reg[15:12]) - 4'b0001: // FPGA_CMD_SET_CONFREG + `FPGA_CMD_SET_CONFREG: begin conf_word <= shift_reg[8:0]; - if (shift_reg[8:0] == 9'b000000001) - begin // LF edge detect - user_byte1 <= 127; // default threshold + if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) + begin + lf_ed_threshold <= 127; // default threshold end end - 4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR - 4'b0011: user_byte1 <= shift_reg[7:0]; // FPGA_CMD_SET_USER_BYTE1 + `FPGA_CMD_SET_DIVISOR: + divisor <= shift_reg[7:0]; + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: + lf_ed_threshold <= shift_reg[7:0]; endcase end @@ -62,7 +84,6 @@ wire [2:0] major_mode = conf_word[8:6]; // For the low-frequency configuration: wire lf_field = conf_word[0]; wire lf_ed_toggle_mode = conf_word[1]; // for lo_edge_detect -wire [7:0] lf_ed_threshold = user_byte1; //----------------------------------------------------------------------------- // And then we instantiate the modules corresponding to each of the FPGA's @@ -106,17 +127,17 @@ lo_edge_detect le( // 001 -- LF edge detect (generic) // 010 -- LF passthrough -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/min_max_tracker.v b/fpga/min_max_tracker.v index 8abd40fb..c47cfd3d 100644 --- a/fpga/min_max_tracker.v +++ b/fpga/min_max_tracker.v @@ -25,7 +25,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, always @(posedge clk) begin case (state) - 0: + 0: // initialize begin if (cur_max_val >= ({1'b0, adc_d} + threshold)) state <= 2; @@ -36,7 +36,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, else if (adc_d <= cur_min_val) cur_min_val <= adc_d; end - 1: + 1: // high phase begin if (cur_max_val <= adc_d) cur_max_val <= adc_d; @@ -46,7 +46,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, max_val <= cur_max_val; end end - 2: + 2: // low phase begin if (adc_d <= cur_min_val) cur_min_val <= adc_d; -- 2.39.2