From 8c944186272136cf4d9a7f28e5f6076ef35c620d Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 5 Dec 2016 13:14:46 +0100 Subject: [PATCH 01/30] Don't keep generated 7020 bitstream in version control. Signed-off-by: Ola Jeppsson --- ...arallella_e16_headless_gpiose_7020.bit.bin | Bin 4045568 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/parallella/fpga/headless_e16_z7020/parallella_e16_headless_gpiose_7020.bit.bin diff --git a/src/parallella/fpga/headless_e16_z7020/parallella_e16_headless_gpiose_7020.bit.bin b/src/parallella/fpga/headless_e16_z7020/parallella_e16_headless_gpiose_7020.bit.bin deleted file mode 100644 index 465d93e8a51c8e98c088761ca2a8197187c4c6f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4045568 zcmeFa3wR}0btby1R61Qc-L^_XZra$`TZ&?<8^;J_g5x~AC1hK87@`KtX2>K~=i$$U zOk#*{+L_GQTL-l{Zj&HGH<-ywG!L70E;za7CK=}v+1DY2^!?(7T=LzyL$1kVzD&3= z&BYG+AQRnxtzG+^I?~arb);4w){<)Pz1CiPRn@=tqpHr{Rf~(O)00FrP6Itb>yD`p zorK6lCLTsi5#_NX;Uy30U7QI$-lFMT$3(+_dp*U`LgdT3X!!kiy|W{Neiv)A?g9-* z3GB`z?nDfpGa~A!*=N0#w#elA4&|W)GGuA^o}cNS^sI)8fFhs>C<2OrBA^H;0*Zhl zpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H; z0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2Or zBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs> zC<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%I zfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`e zihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhl zpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H; z0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2Or zBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs> zC<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%I zfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`e zihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhl zpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H; z0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2Or zBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs> zC<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%I zfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`e zihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhl zpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H; z0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2Or zBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs> zC<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%I zfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`e zihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhl zpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H; z0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2Or zBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs>C<2OrBA^H;0*Zhlpa>`eihv@Z2q*%IfFhs> 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%0A;v(ZV`R8jmCI}tm4Q8 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 zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C7DuGuX*`LJOto`5qwxeeP1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oU)H+ogjO1cDd}pb5)f z1bf&LQri|FUhKn*M{k}*Y{f?0(b*D&72aW(Awvkf9|8mj5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pkzZA%bIz4am zGGl5dk5Rktz|VW=@Al_x!=Pm}_FQs`intH?h{~my=YB`j<#2tinYEsM?^$c^ZR9Bj MIoJU^@Gm>?25}jLN&o-= From c0a4e47870861c14cd46dd615bcfc1d5b3b8910b Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 5 Dec 2016 13:26:55 +0100 Subject: [PATCH 02/30] Add parallella_base intermediate files to gitignore Signed-off-by: Ola Jeppsson --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6225f22e..44a67bf6 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ xgui/ #ASIC proprietary files proprietary/ +# parallella_base intermediate files +src/parallella/fpga/parallella_base/src From f3e7c537f767658200218dfd7749714796323ce7 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 19 May 2019 19:41:39 -0400 Subject: [PATCH 03/30] parallella/fpga: Set CFG_PLATFORM to "ZYNQ" Use oh_verilog_define instead of oh_synthesis_options. The below commit introduced the CFG_PLATFORM variable which we now need to define in our FPGA projects. commit 998f3021cced74e584b829ede8c566e8088c3587 Author: Andreas Olofsson Date: Wed Nov 22 11:32:20 2017 -0500 Fixed elink platform compile errors -Ultrascale changes broke the zynq design -Adding CFG_PLATFORM variable to control compilation target Signed-off-by: Ola Jeppsson --- src/parallella/fpga/headless_e16_z7010/system_params.tcl | 2 +- src/parallella/fpga/headless_e16_z7020/system_params.tcl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parallella/fpga/headless_e16_z7010/system_params.tcl b/src/parallella/fpga/headless_e16_z7010/system_params.tcl index 4ce1a4cf..cce9bdd2 100644 --- a/src/parallella/fpga/headless_e16_z7010/system_params.tcl +++ b/src/parallella/fpga/headless_e16_z7010/system_params.tcl @@ -24,4 +24,4 @@ set constraints_files [list \ ########################################################### # PREPARE FOR SYNTHESIS ########################################################### -set oh_synthesis_options "-verilog_define CFG_ASIC=0" +set oh_verilog_define "CFG_ASIC=0 CFG_PLATFORM=\"ZYNQ\"" diff --git a/src/parallella/fpga/headless_e16_z7020/system_params.tcl b/src/parallella/fpga/headless_e16_z7020/system_params.tcl index 8505cd15..bd03e868 100644 --- a/src/parallella/fpga/headless_e16_z7020/system_params.tcl +++ b/src/parallella/fpga/headless_e16_z7020/system_params.tcl @@ -25,4 +25,4 @@ set constraints_files [list \ ########################################################### # PREPARE FOR SYNTHESIS ########################################################### -set oh_synthesis_options "-verilog_define CFG_ASIC=0" +set oh_verilog_define "CFG_ASIC=0 CFG_PLATFORM=\"ZYNQ\"" From 1f439c05292cee612da1d2f21a23773f331118d8 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 20 May 2019 21:29:34 -0400 Subject: [PATCH 04/30] common: oh_mux: Fix Vivado issues |= operator is not supported. Signed-off-by: Ola Jeppsson --- src/common/hdl/oh_mux.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/hdl/oh_mux.v b/src/common/hdl/oh_mux.v index 7bda282c..6992ea8f 100644 --- a/src/common/hdl/oh_mux.v +++ b/src/common/hdl/oh_mux.v @@ -6,7 +6,7 @@ //############################################################################# module oh_mux #( parameter DW = 1, // width of data inputs - parameter N = 1 // number of inputs + parameter N = 2 // number of inputs ) ( input [N-1:0] sel, // select vector @@ -21,7 +21,7 @@ module oh_mux #( parameter DW = 1, // width of data inputs begin out[DW-1:0] = 'b0; for(i=0;i Date: Mon, 20 May 2019 21:32:36 -0400 Subject: [PATCH 05/30] elink: Fix I/O primitives for Zynq Fix remaining issues for Zynq that were introduced by the Ultrascale+ implementation. Signed-off-by: Ola Jeppsson --- src/elink/hdl/erx_clocks.v | 17 ++++++++++++++++- src/elink/hdl/erx_io.v | 1 + src/elink/hdl/etx_io.v | 31 +++++++++++++++---------------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/elink/hdl/erx_clocks.v b/src/elink/hdl/erx_clocks.v index 3f77218a..46518010 100644 --- a/src/elink/hdl/erx_clocks.v +++ b/src/elink/hdl/erx_clocks.v @@ -12,6 +12,7 @@ module erx_clocks (/*AUTOARG*/ parameter RXCLK_PHASE = 0; // 270; parameter PLL_VCO_MULT = 4; // RX parameter TARGET = `CFG_TARGET; // "XILINX", "ALTERA" etc + parameter PLATFORM = `CFG_PLATFORM; //Override reset counter size for simulation `ifdef TARGET_SIM @@ -210,6 +211,9 @@ module erx_clocks (/*AUTOARG*/ // Idelay controller //########################### + //generate + if(PLATFORM=="ULTRASCALE") + begin : ultrascale `define IDELAYCTRL_WONT_SYNTHESIZE `ifdef IDELAYCTRL_WONT_SYNTHESIZE assign idelay_ready = 'b1; @@ -225,7 +229,18 @@ module erx_clocks (/*AUTOARG*/ .RST(idelay_reset) ); `endif - + end // block: ultrascale + else // PLATFORM="ZYNQ" + begin: zynq + (* IODELAY_GROUP = "IDELAY_GROUP" *) // Group name for IDELAYCTRL + IDELAYCTRL idelayctrl_inst + ( + .RDY(idelay_ready), // check ready flag in reset sequence? + .REFCLK(idelay_ref_clk),//200MHz clk (78ps tap delay) + .RST(idelay_reset)); + end // block: zynq + //endgenerate + end // if (TARGET=="XILINX") endgenerate diff --git a/src/elink/hdl/erx_io.v b/src/elink/hdl/erx_io.v index 4faa3cfd..aca5c939 100644 --- a/src/elink/hdl/erx_io.v +++ b/src/elink/hdl/erx_io.v @@ -318,6 +318,7 @@ module erx_io (/*AUTOARG*/ if(PLATFORM=="ULTRASCALE") begin : ultrascale + genvar j; for(j=0; j<9; j=j+1) begin : gen_idelay `define IDELAYCTRL_WONT_SYNTHESIZE diff --git a/src/elink/hdl/etx_io.v b/src/elink/hdl/etx_io.v index 569be81b..01ba2d89 100644 --- a/src/elink/hdl/etx_io.v +++ b/src/elink/hdl/etx_io.v @@ -214,22 +214,21 @@ module etx_io (/*AUTOARG*/ .O (tx_wr_wait_async)); end endgenerate - -//TODO: Come up with cleaner defines for this -`define ZYNQMP -`ifdef ZYNQMP - IBUFDS - #(.DIFF_TERM ("TRUE"), // Differential termination - .IOSTANDARD (IOSTD_ELINK)) - ibufds_rdwait - (.I (txi_rd_wait_p), - .IB (txi_rd_wait_n), - .O (tx_rd_wait_async)); -`else - //On Parallella this signal comes in single-ended - assign tx_rd_wait_async = txi_rd_wait_p; -`endif - + + generate + if(PLATFORM=="ULTRASCALE") + IBUFDS + #(.DIFF_TERM ("TRUE"), // Differential termination + .IOSTANDARD (IOSTD_ELINK)) + ibufds_rdwait + (.I (txi_rd_wait_p), + .IB (txi_rd_wait_n), + .O (tx_rd_wait_async)); + else // ZYNQ + //On Parallella this signal comes in single-ended + assign tx_rd_wait_async = txi_rd_wait_p; + endgenerate + endmodule // etx_io // Local Variables: // verilog-library-directories:("." "../../emesh/hdl" "../../common/hdl") From a2e31d60999c1dcf2ed25c810a47343eac1d09b8 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 20 May 2019 21:41:42 -0400 Subject: [PATCH 06/30] parallella/fpga: Regenerate block design scripts Signed-off-by: Ola Jeppsson --- .../fpga/headless_e16_z7010/system_bd.tcl | 533 ++++++++++++++++-- .../fpga/headless_e16_z7020/system_bd.tcl | 533 ++++++++++++++++-- 2 files changed, 960 insertions(+), 106 deletions(-) diff --git a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl index 3f3f7daf..b9d5ef46 100644 --- a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl @@ -7,15 +7,25 @@ # IP Integrator Tcl commands easier. ################################################################ +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + ################################################################ # Check if script is running in correct Vivado version. ################################################################ -set scripts_vivado_version 2015.2 +set scripts_vivado_version 2018.2 set current_vivado_version [version -short] if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { puts "" - puts "ERROR: This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script." + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} return 1 } @@ -27,19 +37,18 @@ if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { # To test this script, run the following commands from Vivado Tcl console: # source system_script.tcl -# If you do not already have a project created, -# you can create a project using the following command: -# create_project project_1 myproj -part xc7z010clg400-1 +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. -# CHECKING IF PROJECT EXISTS -if { [get_projects -quiet] eq "" } { - puts "ERROR: Please open or create a project!" - return 1 +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z010clg400-1 } - # CHANGE DESIGN NAME HERE +variable design_name set design_name system # If you do not already have an existing IP Integrator design open, @@ -57,7 +66,7 @@ if { ${design_name} eq "" } { # USE CASES: # 1) Design_name not set - set errMsg "ERROR: Please set the variable to a non-empty value." + set errMsg "Please set the variable to a non-empty value." set nRet 1 } elseif { ${cur_design} ne "" && ${list_cells} eq "" } { @@ -67,23 +76,23 @@ if { ${design_name} eq "" } { # 4): Current design opened AND is empty AND names diff; design_name exists in project. if { $cur_design ne $design_name } { - puts "INFO: Changing value of from <$design_name> to <$cur_design> since current design is empty." + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." set design_name [get_property NAME $cur_design] } - puts "INFO: Constructing design in IPI design <$cur_design>..." + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." } elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { # USE CASES: # 5) Current design opened AND has components AND same names. - set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable to another value." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." set nRet 1 } elseif { [get_files -quiet ${design_name}.bd] ne "" } { # USE CASES: # 6) Current opened design, has components, but diff names, design_name exists in project. # 7) No opened design, design_name exists in project. - set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable to another value." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." set nRet 2 } else { @@ -91,22 +100,57 @@ if { ${design_name} eq "" } { # 8) No opened design, design_name not in project. # 9) Current opened design, has components, but diff names, design_name not in project. - puts "INFO: Currently there is no design <$design_name> in project, so creating one..." + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." create_bd_design $design_name - puts "INFO: Making design <$design_name> as current_bd_design." + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." current_bd_design $design_name } -puts "INFO: Currently the variable is equal to \"$design_name\"." +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." if { $nRet != 0 } { - puts $errMsg + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} return $nRet } +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +www.parallella.org:user:parallella_base:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:ip:xlconcat:2.1\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + ################################################################## # DESIGN PROCs ################################################################## @@ -117,6 +161,9 @@ if { $nRet != 0 } { # procedure reusable. If parentCell is "", will use root. proc create_root_design { parentCell } { + variable script_folder + variable design_name + if { $parentCell eq "" } { set parentCell [get_bd_cells /] } @@ -124,14 +171,14 @@ proc create_root_design { parentCell } { # Get object for parentCell set parentObj [get_bd_cells $parentCell] if { $parentObj == "" } { - puts "ERROR: Unable to find parent cell <$parentCell>!" + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} return } # Make sure parentObj is hier blk set parentType [get_property TYPE $parentObj] if { $parentType ne "hier" } { - puts "ERROR: Parent <$parentObj> has TYPE = <$parentType>. Expected to be ." + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} return } @@ -182,51 +229,431 @@ proc create_root_design { parentCell } { # Create instance: axi_mem_intercon, and set properties set axi_mem_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_mem_intercon ] - set_property -dict [ list CONFIG.NUM_MI {1} ] $axi_mem_intercon + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_mem_intercon # Create instance: parallella_base_0, and set properties set parallella_base_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_base:1.0 parallella_base_0 ] - set_property -dict [ list CONFIG.NGPIO {12} ] $parallella_base_0 + set_property -dict [ list \ + CONFIG.NGPIO {12} \ + ] $parallella_base_0 # Create instance: proc_sys_reset_0, and set properties set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ] # Create instance: processing_system7_0, and set properties set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] - set_property -dict [ list CONFIG.PCW_CORE0_FIQ_INTR {0} \ -CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ -CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ -CONFIG.PCW_EN_CLK3_PORT {1} CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ -CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ -CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ -CONFIG.PCW_I2C0_I2C0_IO {EMIO} CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_I2C0_RESET_ENABLE {0} CONFIG.PCW_IRQ_F2P_INTR {1} \ -CONFIG.PCW_IRQ_F2P_MODE {DIRECT} CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ -CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ -CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ -CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ -CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} CONFIG.PCW_UIPARAM_DDR_CL {9} \ -CONFIG.PCW_UIPARAM_DDR_CWL {9} CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ -CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ -CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ -CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ -CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ -CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ -CONFIG.PCW_UIPARAM_DDR_T_RCD {9} CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ -CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_USB0_RESET_ENABLE {0} CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_USE_M_AXI_GP1 {1} \ -CONFIG.PCW_USE_S_AXI_HP1 {1} ] $processing_system7_0 + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {666.666687} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.062893} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {40} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {100000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1333.333} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {53} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {3} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {48} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1600.000} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {4} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x3FFFFFFF} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {EMIO} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_CLK3_PORT {1} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {1} \ + CONFIG.PCW_EN_EMIO_I2C0 {1} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {1} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_SDIO1 {1} \ + CONFIG.PCW_EN_UART1 {1} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {1} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK_CLK3_BUF {TRUE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {64} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {1} \ + CONFIG.PCW_I2C0_GRP_INT_IO {EMIO} \ + CONFIG.PCW_I2C0_I2C0_IO {EMIO} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {30} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {1} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {inout} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {inout} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {in} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {out} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {in} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {inout} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {inout} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {in} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {inout} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {in} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#UART 1#UART 1#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO#GPIO} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#tx#rx#data[0]#cmd#clk#data[1]#data[2]#data[3]#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#gpio[52]#gpio[53]} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {400.000000} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} \ + CONFIG.PCW_UIPARAM_DDR_CL {9} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {9} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {9} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {0} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_USB1_IO {MIO 40 .. 51} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {1} \ + CONFIG.PCW_USE_S_AXI_HP1 {1} \ + ] $processing_system7_0 # Create instance: processing_system7_0_axi_periph, and set properties set processing_system7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 processing_system7_0_axi_periph ] - set_property -dict [ list CONFIG.NUM_MI {1} ] $processing_system7_0_axi_periph + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $processing_system7_0_axi_periph # Create instance: sys_concat_intc, and set properties set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ] - set_property -dict [ list CONFIG.NUM_PORTS {16} ] $sys_concat_intc + set_property -dict [ list \ + CONFIG.NUM_PORTS {16} \ + ] $sys_concat_intc # Create interface connections connect_bd_intf_net -intf_net axi_mem_intercon_M00_AXI [get_bd_intf_pins axi_mem_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] @@ -280,9 +707,9 @@ CONFIG.PCW_USE_S_AXI_HP1 {1} ] $processing_system7_0 connect_bd_net -net txi_wr_wait_p_1 [get_bd_ports txi_wr_wait_p] [get_bd_pins parallella_base_0/txi_wr_wait_p] # Create address segments - create_bd_addr_seg -range 0x40000000 -offset 0x0 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite - + # Restore current instance current_bd_instance $oldCurInst diff --git a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl index 6dc43082..af940e09 100644 --- a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl @@ -7,15 +7,25 @@ # IP Integrator Tcl commands easier. ################################################################ +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + ################################################################ # Check if script is running in correct Vivado version. ################################################################ -set scripts_vivado_version 2015.2 +set scripts_vivado_version 2018.2 set current_vivado_version [version -short] if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { puts "" - puts "ERROR: This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script." + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} return 1 } @@ -27,19 +37,18 @@ if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { # To test this script, run the following commands from Vivado Tcl console: # source system_script.tcl -# If you do not already have a project created, -# you can create a project using the following command: -# create_project project_1 myproj -part xc7z020clg400-1 +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. -# CHECKING IF PROJECT EXISTS -if { [get_projects -quiet] eq "" } { - puts "ERROR: Please open or create a project!" - return 1 +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 } - # CHANGE DESIGN NAME HERE +variable design_name set design_name system # If you do not already have an existing IP Integrator design open, @@ -57,7 +66,7 @@ if { ${design_name} eq "" } { # USE CASES: # 1) Design_name not set - set errMsg "ERROR: Please set the variable to a non-empty value." + set errMsg "Please set the variable to a non-empty value." set nRet 1 } elseif { ${cur_design} ne "" && ${list_cells} eq "" } { @@ -67,23 +76,23 @@ if { ${design_name} eq "" } { # 4): Current design opened AND is empty AND names diff; design_name exists in project. if { $cur_design ne $design_name } { - puts "INFO: Changing value of from <$design_name> to <$cur_design> since current design is empty." + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." set design_name [get_property NAME $cur_design] } - puts "INFO: Constructing design in IPI design <$cur_design>..." + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." } elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { # USE CASES: # 5) Current design opened AND has components AND same names. - set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable to another value." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." set nRet 1 } elseif { [get_files -quiet ${design_name}.bd] ne "" } { # USE CASES: # 6) Current opened design, has components, but diff names, design_name exists in project. # 7) No opened design, design_name exists in project. - set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable to another value." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." set nRet 2 } else { @@ -91,22 +100,57 @@ if { ${design_name} eq "" } { # 8) No opened design, design_name not in project. # 9) Current opened design, has components, but diff names, design_name not in project. - puts "INFO: Currently there is no design <$design_name> in project, so creating one..." + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." create_bd_design $design_name - puts "INFO: Making design <$design_name> as current_bd_design." + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." current_bd_design $design_name } -puts "INFO: Currently the variable is equal to \"$design_name\"." +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." if { $nRet != 0 } { - puts $errMsg + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} return $nRet } +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +www.parallella.org:user:parallella_base:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:ip:xlconcat:2.1\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + ################################################################## # DESIGN PROCs ################################################################## @@ -117,6 +161,9 @@ if { $nRet != 0 } { # procedure reusable. If parentCell is "", will use root. proc create_root_design { parentCell } { + variable script_folder + variable design_name + if { $parentCell eq "" } { set parentCell [get_bd_cells /] } @@ -124,14 +171,14 @@ proc create_root_design { parentCell } { # Get object for parentCell set parentObj [get_bd_cells $parentCell] if { $parentObj == "" } { - puts "ERROR: Unable to find parent cell <$parentCell>!" + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} return } # Make sure parentObj is hier blk set parentType [get_property TYPE $parentObj] if { $parentType ne "hier" } { - puts "ERROR: Parent <$parentObj> has TYPE = <$parentType>. Expected to be ." + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} return } @@ -182,51 +229,431 @@ proc create_root_design { parentCell } { # Create instance: axi_mem_intercon, and set properties set axi_mem_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_mem_intercon ] - set_property -dict [ list CONFIG.NUM_MI {1} ] $axi_mem_intercon + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_mem_intercon # Create instance: parallella_base_0, and set properties set parallella_base_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_base:1.0 parallella_base_0 ] - set_property -dict [ list CONFIG.NGPIO {24} ] $parallella_base_0 + set_property -dict [ list \ + CONFIG.NGPIO {24} \ + ] $parallella_base_0 # Create instance: proc_sys_reset_0, and set properties set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ] # Create instance: processing_system7_0, and set properties set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] - set_property -dict [ list CONFIG.PCW_CORE0_FIQ_INTR {0} \ -CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ -CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ -CONFIG.PCW_EN_CLK3_PORT {1} CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ -CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ -CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ -CONFIG.PCW_I2C0_I2C0_IO {EMIO} CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_I2C0_RESET_ENABLE {0} CONFIG.PCW_IRQ_F2P_INTR {1} \ -CONFIG.PCW_IRQ_F2P_MODE {DIRECT} CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ -CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ -CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ -CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ -CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} CONFIG.PCW_UIPARAM_DDR_CL {9} \ -CONFIG.PCW_UIPARAM_DDR_CWL {9} CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ -CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ -CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ -CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ -CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ -CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ -CONFIG.PCW_UIPARAM_DDR_T_RCD {9} CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ -CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_USB0_RESET_ENABLE {0} CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ -CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_USE_M_AXI_GP1 {1} \ -CONFIG.PCW_USE_S_AXI_HP1 {1} ] $processing_system7_0 + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {666.666687} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.062893} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {40} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {100000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1333.333} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {53} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {3} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {48} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1600.000} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {4} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x3FFFFFFF} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {EMIO} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_CLK3_PORT {1} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {1} \ + CONFIG.PCW_EN_EMIO_I2C0 {1} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {1} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_SDIO1 {1} \ + CONFIG.PCW_EN_UART1 {1} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {1} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK_CLK3_BUF {TRUE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {64} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {1} \ + CONFIG.PCW_I2C0_GRP_INT_IO {EMIO} \ + CONFIG.PCW_I2C0_I2C0_IO {EMIO} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {30} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {1} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {inout} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {inout} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {in} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {out} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {in} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {inout} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {inout} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {in} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {inout} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {in} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#UART 1#UART 1#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO#GPIO} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#tx#rx#data[0]#cmd#clk#data[1]#data[2]#data[3]#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#gpio[52]#gpio[53]} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {400.000000} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} \ + CONFIG.PCW_UIPARAM_DDR_CL {9} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {9} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {9} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {0} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_USB1_IO {MIO 40 .. 51} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {1} \ + CONFIG.PCW_USE_S_AXI_HP1 {1} \ + ] $processing_system7_0 # Create instance: processing_system7_0_axi_periph, and set properties set processing_system7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 processing_system7_0_axi_periph ] - set_property -dict [ list CONFIG.NUM_MI {1} ] $processing_system7_0_axi_periph + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $processing_system7_0_axi_periph # Create instance: sys_concat_intc, and set properties set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ] - set_property -dict [ list CONFIG.NUM_PORTS {16} ] $sys_concat_intc + set_property -dict [ list \ + CONFIG.NUM_PORTS {16} \ + ] $sys_concat_intc # Create interface connections connect_bd_intf_net -intf_net axi_mem_intercon_M00_AXI [get_bd_intf_pins axi_mem_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] @@ -280,9 +707,9 @@ CONFIG.PCW_USE_S_AXI_HP1 {1} ] $processing_system7_0 connect_bd_net -net txi_wr_wait_p_1 [get_bd_ports txi_wr_wait_p] [get_bd_pins parallella_base_0/txi_wr_wait_p] # Create address segments - create_bd_addr_seg -range 0x40000000 -offset 0x0 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite - + # Restore current instance current_bd_instance $oldCurInst From 1be6358dfe70d6949098f5d62fddc81d029707bc Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 20 May 2019 21:45:18 -0400 Subject: [PATCH 07/30] xilibs: Upgrade IPs to Vivado 2018.2 Signed-off-by: Ola Jeppsson --- src/xilibs/ip/fifo_async_104x32.xci | 960 ++++++++++++++++------------ 1 file changed, 534 insertions(+), 426 deletions(-) diff --git a/src/xilibs/ip/fifo_async_104x32.xci b/src/xilibs/ip/fifo_async_104x32.xci index b2e4cc53..11ca18ad 100644 --- a/src/xilibs/ip/fifo_async_104x32.xci +++ b/src/xilibs/ip/fifo_async_104x32.xci @@ -1,428 +1,536 @@ - - xilinx.com - xci - unknown - 1.0 - - - fifo_async_104x32 - - - 100000000 - 100000000 - 100000000 - 100000000 - 100000000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 1 - 1 - 1 - 1 - 4 - 0 - 32 - 1 - 1 - 1 - 64 - 1 - 8 - 1 - 1 - 1 - 1 - 0 - 0 - 5 - BlankString - 104 - 1 - 32 - 64 - 1 - 64 - 2 - 0 - 104 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - zynquplus - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - 2 - BlankString - 1 - 0 - 0 - 0 - 1 - 0 - 512x72 - 1kx18 - 512x36 - 512x72 - 512x36 - 512x72 - 512x36 - 2 - 1022 - 1022 - 1022 - 1022 - 1022 - 1022 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 16 - 1023 - 1023 - 1023 - 1023 - 1023 - 1023 - 15 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 5 - 32 - 1 - 5 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 5 - 32 - 1024 - 16 - 1024 - 16 - 1024 - 16 - 1 - 5 - 10 - 4 - 10 - 4 - 10 - 4 - 1 - 32 - 0 - 0 - false - false - false - 0 - 0 - Slave_Interface_Clock_Enable - Common_Clock - fifo_async_104x32 - 64 - false - 5 - false - false - 0 - 2 - 1022 - 1022 - 1022 - 1022 - 1022 - 1022 - 3 - false - false - false - false - false - false - false - false - false - Hard_ECC - false - false - false - false - false - false - true - false - false - true - Data_FIFO - Data_FIFO - Data_FIFO - Data_FIFO - Data_FIFO - Data_FIFO - Common_Clock_Block_RAM - Common_Clock_Block_RAM - Common_Clock_Block_RAM - Common_Clock_Block_RAM - Common_Clock_Block_RAM - Common_Clock_Block_RAM - Independent_Clocks_Distributed_RAM - 0 - 16 - 1023 - 1023 - 1023 - 1023 - 1023 - 1023 - 15 - false - false - false - 0 - Native - false - false - false - false - false - false - false - false - false - false - false - false - false - false - 104 - 32 - 1024 - 16 - 1024 - 16 - 1024 - 16 - false - 104 - 32 - Embedded_Reg - false - false - Active_High - Active_High - AXI4 - Standard_FIFO - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - No_Programmable_Empty_Threshold - Single_Programmable_Full_Threshold_Constant - No_Programmable_Full_Threshold - No_Programmable_Full_Threshold - No_Programmable_Full_Threshold - No_Programmable_Full_Threshold - No_Programmable_Full_Threshold - No_Programmable_Full_Threshold - READ_WRITE - 0 - 1 - true - 5 - Fully_Registered - Fully_Registered - Fully_Registered - Fully_Registered - Fully_Registered - Fully_Registered - true - Asynchronous_Reset - false - 1 - 0 - 0 - 1 - 1 - 4 - false - false - Active_High - Active_High - true - false - false - false - false - Active_High - 0 - false - Active_High - 1 - false - 5 - false - FIFO - false - false - false - false - FIFO - FIFO - 2 - 2 - false - FIFO - FIFO - FIFO - zynquplus - - xczu9eg - ffvb1156 - VERILOG - es2 - MIXED - -2 - I - TRUE - TRUE - IP_Flow - 3 - TRUE - . - - . - 2016.4 - OUT_OF_CONTEXT - - - - - - - - - - - - - + + xilinx.com + xci + unknown + 1.0 + + + fifo_async_104x32 + + + + + + 100000000 + 0.000 + + + 100000000 + 0.000 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + + + 100000000 + 0.000 + + 100000000 + 0.000 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + + + 100000000 + 0.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 1 + 1 + 1 + 1 + 4 + 0 + 32 + 1 + 1 + 1 + 64 + 1 + 8 + 1 + 1 + 1 + 1 + 0 + 0 + 5 + BlankString + 104 + 1 + 32 + 64 + 1 + 64 + 2 + 0 + 104 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + zynq + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 2 + BlankString + 1 + 0 + 0 + 0 + 1 + 0 + 512x72 + 1kx18 + 512x36 + 1kx36 + 512x36 + 1kx36 + 512x36 + 2 + 1022 + 1022 + 1022 + 1022 + 1022 + 1022 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 16 + 1023 + 1023 + 1023 + 1023 + 1023 + 1023 + 15 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 5 + 32 + 1 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 5 + 32 + 1024 + 16 + 1024 + 16 + 1024 + 16 + 1 + 5 + 10 + 4 + 10 + 4 + 10 + 4 + 1 + 32 + 0 + 0 + false + false + false + 0 + 0 + Slave_Interface_Clock_Enable + Common_Clock + fifo_async_104x32 + 64 + false + 5 + false + false + 0 + 2 + 1022 + 1022 + 1022 + 1022 + 1022 + 1022 + 3 + false + false + false + false + false + false + false + false + false + Hard_ECC + false + false + false + false + false + false + true + false + false + true + Data_FIFO + Data_FIFO + Data_FIFO + Data_FIFO + Data_FIFO + Data_FIFO + Common_Clock_Block_RAM + Common_Clock_Block_RAM + Common_Clock_Block_RAM + Common_Clock_Block_RAM + Common_Clock_Block_RAM + Common_Clock_Block_RAM + Independent_Clocks_Distributed_RAM + 0 + 16 + 1023 + 1023 + 1023 + 1023 + 1023 + 1023 + 15 + false + false + false + 0 + Native + false + false + false + false + false + false + false + false + false + false + false + false + false + false + 104 + 32 + 1024 + 16 + 1024 + 16 + 1024 + 16 + false + 104 + 32 + Embedded_Reg + false + false + Active_High + Active_High + AXI4 + Standard_FIFO + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + No_Programmable_Empty_Threshold + Single_Programmable_Full_Threshold_Constant + No_Programmable_Full_Threshold + No_Programmable_Full_Threshold + No_Programmable_Full_Threshold + No_Programmable_Full_Threshold + No_Programmable_Full_Threshold + No_Programmable_Full_Threshold + READ_WRITE + 0 + 1 + true + 5 + Fully_Registered + Fully_Registered + Fully_Registered + Fully_Registered + Fully_Registered + Fully_Registered + true + Asynchronous_Reset + false + 1 + 0 + 0 + 1 + 1 + 4 + false + false + Active_High + Active_High + true + false + false + false + false + Active_High + 0 + false + Active_High + 1 + false + 5 + false + FIFO + false + false + false + false + FIFO + FIFO + 2 + 2 + false + FIFO + FIFO + FIFO + zynq + + xc7z020 + clg400 + VERILOG + + MIXED + -1 + + TRUE + TRUE + IP_Flow + 2 + TRUE + . + + . + 2018.2.2 + OUT_OF_CONTEXT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b2d93da601dabc2f48191cf7e66b99184f336660 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sat, 25 May 2019 18:11:59 -0400 Subject: [PATCH 08/30] parallella/fpga: Fix Makefile clean target --- src/parallella/fpga/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/parallella/fpga/Makefile b/src/parallella/fpga/Makefile index e21d4e2e..a6a1dfaa 100644 --- a/src/parallella/fpga/Makefile +++ b/src/parallella/fpga/Makefile @@ -1,4 +1,3 @@ - .PHONY: all clean all: @@ -7,6 +6,6 @@ all: make -C headless_e16_z7020/ all clean: - make -C headless/ clean + make -C parallella_base/ clean make -C headless_e16_z7010/ clean make -C headless_e16_z7020/ clean From 8413afddc5a344b4caeebd328680b4017a539a86 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sat, 25 May 2019 18:54:24 -0400 Subject: [PATCH 09/30] Don't keep generated 7020 bitstream in version control Missed this one in the previous commit. --- .../headless_e16_z7020/parallella.bit.bin | Bin 4045568 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/parallella/fpga/headless_e16_z7020/parallella.bit.bin diff --git a/src/parallella/fpga/headless_e16_z7020/parallella.bit.bin b/src/parallella/fpga/headless_e16_z7020/parallella.bit.bin deleted file mode 100644 index 9e1a21373f4aad7049f4bff9ec18fcc817112ad4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4045568 zcmeFa4SZz9buW1C)opRrh|z7iXDpZjNIF1u*2=>ph zvk6XkJ7gcRt3}Va(Xd!UX83TtPMg@_!;bB|M-sosTSs6*Scl(+@dqR?u@^h>dwI?- zAscYAaq_hPQ+2ERc1xNOBeh2AoFm<;I;T$6t@}Uqb#GVQySR9KdW?uBXsF<|-aCE& zBM_-Tg(L7Opwu^Hc^ilDX&ebXK7yH4M+GC_eKUo@Lg3PxVC2_s{-v$}`aP`8x(hTC zM98-WKL;N?M+DSW&!6>HIs%pI8>EL4NRg(ITYtW9%CX`K0)l`bAP5Kof`A|(2nYg# zfFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|( z2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Ko zf`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`b zAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_` z0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qD zARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U z2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg# zfFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|( z2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Ko zf`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`b zAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_` z0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qD zARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U z2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg# zfFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|( z2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Ko zf`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`b zAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_` z0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qD zARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U z2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg# zfFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|( z2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Ko zf`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`b zAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_` z0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qD zARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U z2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg# zfFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|( z2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Ko zf`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`b zAP5Kof`A|(2nYg#fFK|U2m*qDARq_`0)l`bAP5Kof`A|(2nYg#fFK|U2m*qDARq_` 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 Date: Sun, 26 May 2019 12:58:27 -0400 Subject: [PATCH 10/30] parallella/fpga: Use offset 0 over 8 for hdmi_d pins This is in preparation of adding HDMI block designs for 7020 and 7010. For some reason Vivado automatically strips removes the offset during synthesis(?) which breaks the constraints. --- .../fpga/headless_e16_z7010/system_bd.tcl | 2 +- .../fpga/headless_e16_z7020/system_bd.tcl | 4 +-- src/parallella/fpga/parallella_io.xdc | 32 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl index b9d5ef46..cff1628a 100644 --- a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl @@ -198,7 +198,7 @@ proc create_root_design { parentCell } { set gpio_n [ create_bd_port -dir IO -from 11 -to 0 gpio_n ] set gpio_p [ create_bd_port -dir IO -from 11 -to 0 gpio_p ] set hdmi_clk [ create_bd_port -dir O hdmi_clk ] - set hdmi_d [ create_bd_port -dir O -from 23 -to 8 hdmi_d ] + set hdmi_d [ create_bd_port -dir O -from 15 -to 0 hdmi_d ] set hdmi_de [ create_bd_port -dir O hdmi_de ] set hdmi_hsync [ create_bd_port -dir O hdmi_hsync ] set hdmi_int [ create_bd_port -dir I hdmi_int ] diff --git a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl index af940e09..9ab45f6c 100644 --- a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl @@ -197,8 +197,8 @@ proc create_root_design { parentCell } { set chip_nreset [ create_bd_port -dir O chip_nreset ] set gpio_n [ create_bd_port -dir IO -from 23 -to 0 gpio_n ] set gpio_p [ create_bd_port -dir IO -from 23 -to 0 gpio_p ] - set hdmi_clk [ create_bd_port -dir O hdmi_clk ] - set hdmi_d [ create_bd_port -dir O -from 23 -to 8 hdmi_d ] + set hdmi_clk [ create_bd_port -dir O -type clk hdmi_clk ] + set hdmi_d [ create_bd_port -dir O -from 15 -to 0 hdmi_d ] set hdmi_de [ create_bd_port -dir O hdmi_de ] set hdmi_hsync [ create_bd_port -dir O hdmi_hsync ] set hdmi_int [ create_bd_port -dir I hdmi_int ] diff --git a/src/parallella/fpga/parallella_io.xdc b/src/parallella/fpga/parallella_io.xdc index f66a7ec0..5b9cb475 100644 --- a/src/parallella/fpga/parallella_io.xdc +++ b/src/parallella/fpga/parallella_io.xdc @@ -9,22 +9,22 @@ set_property CONFIG_VOLTAGE 3.3 [current_design] ####################### #TODO: Include for hdmi design set_property IOSTANDARD LVCMOS25 [get_ports {hdmi_*}] -set_property PACKAGE_PIN Y18 [get_ports {hdmi_d[8]}] -set_property PACKAGE_PIN W18 [get_ports {hdmi_d[9]}] -set_property PACKAGE_PIN V18 [get_ports {hdmi_d[10]}] -set_property PACKAGE_PIN V15 [get_ports {hdmi_d[11]}] -set_property PACKAGE_PIN R18 [get_ports {hdmi_d[12]}] -set_property PACKAGE_PIN P18 [get_ports {hdmi_d[13]}] -set_property PACKAGE_PIN Y19 [get_ports {hdmi_d[14]}] -set_property PACKAGE_PIN W19 [get_ports {hdmi_d[15]}] -set_property PACKAGE_PIN W15 [get_ports {hdmi_d[16]}] -set_property PACKAGE_PIN T19 [get_ports {hdmi_d[17]}] -set_property PACKAGE_PIN R19 [get_ports {hdmi_d[18]}] -set_property PACKAGE_PIN P19 [get_ports {hdmi_d[19]}] -set_property PACKAGE_PIN W20 [get_ports {hdmi_d[20]}] -set_property PACKAGE_PIN V20 [get_ports {hdmi_d[21]}] -set_property PACKAGE_PIN U20 [get_ports {hdmi_d[22]}] -set_property PACKAGE_PIN T20 [get_ports {hdmi_d[23]}] +set_property PACKAGE_PIN Y18 [get_ports {hdmi_d[0]}] +set_property PACKAGE_PIN W18 [get_ports {hdmi_d[1]}] +set_property PACKAGE_PIN V18 [get_ports {hdmi_d[2]}] +set_property PACKAGE_PIN V15 [get_ports {hdmi_d[3]}] +set_property PACKAGE_PIN R18 [get_ports {hdmi_d[4]}] +set_property PACKAGE_PIN P18 [get_ports {hdmi_d[5]}] +set_property PACKAGE_PIN Y19 [get_ports {hdmi_d[6]}] +set_property PACKAGE_PIN W19 [get_ports {hdmi_d[7]}] +set_property PACKAGE_PIN W15 [get_ports {hdmi_d[8]}] +set_property PACKAGE_PIN T19 [get_ports {hdmi_d[9]}] +set_property PACKAGE_PIN R19 [get_ports {hdmi_d[10]}] +set_property PACKAGE_PIN P19 [get_ports {hdmi_d[11]}] +set_property PACKAGE_PIN W20 [get_ports {hdmi_d[12]}] +set_property PACKAGE_PIN V20 [get_ports {hdmi_d[13]}] +set_property PACKAGE_PIN U20 [get_ports {hdmi_d[14]}] +set_property PACKAGE_PIN T20 [get_ports {hdmi_d[15]}] set_property PACKAGE_PIN R17 [get_ports hdmi_clk] set_property PACKAGE_PIN V17 [get_ports hdmi_vsync] set_property PACKAGE_PIN T17 [get_ports hdmi_hsync] From 339e6621cd7e9f51e41abf2141d629cef0720fa3 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 13:06:05 -0400 Subject: [PATCH 11/30] parallella/fpga: Add hdmi_e16_z7020 project Initial import from github.com/peteasa/parallella-fpga.git TODO: Need to add ADI IPs to the repository. Not tested. --- src/parallella/fpga/Makefile | 2 + src/parallella/fpga/hdmi_e16_z7020/Makefile | 34 + .../fpga/hdmi_e16_z7020/bit2bin.bif | 6 + src/parallella/fpga/hdmi_e16_z7020/build.sh | 6 + src/parallella/fpga/hdmi_e16_z7020/dummy.elf | Bin 0 -> 328402 bytes src/parallella/fpga/hdmi_e16_z7020/run.tcl | 12 + .../fpga/hdmi_e16_z7020/system_bd.tcl | 909 ++++++++++++++++++ .../fpga/hdmi_e16_z7020/system_params.tcl | 28 + 8 files changed, 997 insertions(+) create mode 100644 src/parallella/fpga/hdmi_e16_z7020/Makefile create mode 100644 src/parallella/fpga/hdmi_e16_z7020/bit2bin.bif create mode 100644 src/parallella/fpga/hdmi_e16_z7020/build.sh create mode 100644 src/parallella/fpga/hdmi_e16_z7020/dummy.elf create mode 100644 src/parallella/fpga/hdmi_e16_z7020/run.tcl create mode 100644 src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl create mode 100644 src/parallella/fpga/hdmi_e16_z7020/system_params.tcl diff --git a/src/parallella/fpga/Makefile b/src/parallella/fpga/Makefile index a6a1dfaa..b5cda72e 100644 --- a/src/parallella/fpga/Makefile +++ b/src/parallella/fpga/Makefile @@ -4,8 +4,10 @@ all: make -C parallella_base/ all make -C headless_e16_z7010/ all make -C headless_e16_z7020/ all + make -C hdmi_e16_z7020/ all clean: make -C parallella_base/ clean make -C headless_e16_z7010/ clean make -C headless_e16_z7020/ clean + make -C hdmi_e16_z7020/ clean diff --git a/src/parallella/fpga/hdmi_e16_z7020/Makefile b/src/parallella/fpga/hdmi_e16_z7020/Makefile new file mode 100644 index 00000000..2adf155d --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/Makefile @@ -0,0 +1,34 @@ + +M_DEPS := run.tcl +M_DEPS += ../parallella_base/parallella_base.xpr +M_DEPS += ../parallella_base/run.tcl + +M_VIVADO := vivado -mode batch -source + +M_FLIST := *.cache +M_FLIST += *.data +M_FLIST += *.xpr +M_FLIST += *.log +M_FLIST += *.jou +M_FLIST += xgui +M_FLIST += *.runs +M_FLIST += *.srcs +M_FLIST += *.sdk +M_FLIST += .Xil +M_FLIST += parallella_e16_hdmi_gpiose_7020.bit.bin +M_FLIST += system_wrapper.bit.bin +M_FLIST += reports +M_FLIST += results +M_FLIST += system.hw +M_FLIST += system.ip_user_files + +.PHONY: all clean + +all: $(M_DEPS) + rm -f system_wrapper.bit.bin bit2bin.bin + $(M_VIVADO) run.tcl + bootgen -image bit2bin.bif -split bin + cp -f system_wrapper.bit.bin parallella_e16_hdmi_gpiose_7020.bit.bin + +clean: + rm -rf $(M_FLIST) diff --git a/src/parallella/fpga/hdmi_e16_z7020/bit2bin.bif b/src/parallella/fpga/hdmi_e16_z7020/bit2bin.bif new file mode 100644 index 00000000..df3de64e --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/bit2bin.bif @@ -0,0 +1,6 @@ +the_ROM_image: +{ + [bootloader]dummy.elf + ./system.runs/impl_1/system_wrapper.bit +} + diff --git a/src/parallella/fpga/hdmi_e16_z7020/build.sh b/src/parallella/fpga/hdmi_e16_z7020/build.sh new file mode 100644 index 00000000..c43fc220 --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +rm system_wrapper.bit.bin bit2bin.bin +vivado -mode batch -source run.tcl +bootgen -image bit2bin.bif -split bin +cp system_wrapper.bit.bin parallella_e16_hdmi_gpiose_7020.bit.bin +#archive results based on time stamp diff --git a/src/parallella/fpga/hdmi_e16_z7020/dummy.elf b/src/parallella/fpga/hdmi_e16_z7020/dummy.elf new file mode 100644 index 0000000000000000000000000000000000000000..6d0b3e0afab059b2d58e0c577ead84b7fd1d0b80 GIT binary patch literal 328402 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 literal 0 HcmV?d00001 diff --git a/src/parallella/fpga/hdmi_e16_z7020/run.tcl b/src/parallella/fpga/hdmi_e16_z7020/run.tcl new file mode 100644 index 00000000..0ab34afc --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/run.tcl @@ -0,0 +1,12 @@ + +#STEP1: DEFINE KEY PARAMETERS +source ./system_params.tcl + +#STEP2: CREATE PROJECT AND READ IN FILES +source ../../../common/fpga/system_init.tcl + +#STEP 3 (OPTIONAL): EDIT system.bd in VIVADO gui, then go to STEP 4. +##... + +#STEP 4: SYNTEHSIZE AND CREATE BITSTRAM +source ../../../common/fpga/system_build.tcl diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl new file mode 100644 index 00000000..cf813b32 --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl @@ -0,0 +1,909 @@ + +################################################################ +# This is a generated script based on design: system +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source system_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name system + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +www.parallella.org:user:parallella_base:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:ip:xlconcat:2.1\ +analog.com:user:axi_clkgen:1.0\ +analog.com:user:axi_hdmi_tx:1.0\ +analog.com:user:axi_spdif_tx:1.0\ +xilinx.com:ip:axi_vdma:6.3\ +xilinx.com:ip:clk_wiz:6.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + +# Hierarchical cell: hdmi_0 +proc create_hier_cell_hdmi_0 { parentCell nameHier } { + + variable script_folder + + if { $parentCell eq "" || $nameHier eq "" } { + catch {common::send_msg_id "BD_TCL-102" "ERROR" "create_hier_cell_hdmi_0() - Empty argument(s)!"} + return + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + # Create cell and set as current instance + set hier_obj [create_bd_cell -type hier $nameHier] + current_bd_instance $hier_obj + + # Create interface pins + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:axis_rtl:1.0 DMA_ACK + create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:axis_rtl:1.0 DMA_REQ + create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 M00_AXI + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI_LITE + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 s_axi1 + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 s_axi2 + + # Create pins + create_bd_pin -dir I -from 0 -to 0 -type rst axi_resetn + create_bd_pin -dir I clk + create_bd_pin -dir O -from 15 -to 0 hdmi_16_data + create_bd_pin -dir O hdmi_16_data_e + create_bd_pin -dir O hdmi_16_hsync + create_bd_pin -dir O hdmi_16_vsync + create_bd_pin -dir O -type clk hdmi_out_clk + create_bd_pin -dir O -type intr mm2s_introut + create_bd_pin -dir I -type clk s_axi_aclk + create_bd_pin -dir O spdif_tx_o + + # Create instance: axi_clkgen_0, and set properties + set axi_clkgen_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_clkgen:1.0 axi_clkgen_0 ] + + # Create instance: axi_hdmi_tx_0, and set properties + set axi_hdmi_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_hdmi_tx:1.0 axi_hdmi_tx_0 ] + + # Create instance: axi_interconnect_0, and set properties + set axi_interconnect_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_interconnect_0 ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_interconnect_0 + + # Create instance: axi_spdif_tx_0, and set properties + set axi_spdif_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_spdif_tx:1.0 axi_spdif_tx_0 ] + set_property -dict [ list \ + CONFIG.DMA_TYPE {1} \ + CONFIG.S_AXI_ADDRESS_WIDTH {16} \ + ] $axi_spdif_tx_0 + + # Create instance: axi_vdma_0, and set properties + set axi_vdma_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_vdma:6.3 axi_vdma_0 ] + set_property -dict [ list \ + CONFIG.c_include_s2mm {0} \ + CONFIG.c_m_axis_mm2s_tdata_width {64} \ + CONFIG.c_use_mm2s_fsync {1} \ + ] $axi_vdma_0 + + # Create instance: clk_wiz_0, and set properties + set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] + set_property -dict [ list \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.CLKOUT1_JITTER {327.996} \ + CONFIG.CLKOUT1_PHASE_ERROR {264.435} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {12.288} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {44.375} \ + CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {80.250} \ + CONFIG.MMCM_DIVCLK_DIVIDE {9} \ + CONFIG.PRIM_IN_FREQ {200.000} \ + CONFIG.RESET_PORT {resetn} \ + CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.USE_LOCKED {false} \ + ] $clk_wiz_0 + + # Create interface connections + connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] + connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] + connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_vdma_0/S_AXI_LITE] + connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] + connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] + connect_bd_intf_net -intf_net axi_vdma_0_M_AXI_MM2S [get_bd_intf_pins axi_interconnect_0/S00_AXI] [get_bd_intf_pins axi_vdma_0/M_AXI_MM2S] + connect_bd_intf_net -intf_net s_axi1_1 [get_bd_intf_pins s_axi1] [get_bd_intf_pins axi_clkgen_0/s_axi] + connect_bd_intf_net -intf_net s_axi2_1 [get_bd_intf_pins s_axi2] [get_bd_intf_pins axi_hdmi_tx_0/s_axi] + + # Create port connections + connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] + connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] + connect_bd_net -net axi_hdmi_tx_0_vdma_fs [get_bd_pins axi_vdma_0/mm2s_fsync] + connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_hdmi_tx_0/vdma_ready] [get_bd_pins axi_vdma_0/m_axis_mm2s_tready] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins axi_vdma_0/axi_resetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] + connect_bd_net -net axi_vdma_0_m_axis_mm2s_tdata [get_bd_pins axi_hdmi_tx_0/vdma_data] [get_bd_pins axi_vdma_0/m_axis_mm2s_tdata] + connect_bd_net -net axi_vdma_0_m_axis_mm2s_tvalid [get_bd_pins axi_hdmi_tx_0/vdma_valid] [get_bd_pins axi_vdma_0/m_axis_mm2s_tvalid] + connect_bd_net -net axi_vdma_0_mm2s_introut [get_bd_pins mm2s_introut] [get_bd_pins axi_vdma_0/mm2s_introut] + connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] + connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] + connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] [get_bd_pins axi_vdma_0/m_axi_mm2s_aclk] [get_bd_pins axi_vdma_0/m_axis_mm2s_aclk] [get_bd_pins axi_vdma_0/s_axi_lite_aclk] + + # Restore current instance + current_bd_instance $oldCurInst +} + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set cclk_n [ create_bd_port -dir O cclk_n ] + set cclk_p [ create_bd_port -dir O cclk_p ] + set chip_nreset [ create_bd_port -dir O chip_nreset ] + set gpio_n [ create_bd_port -dir IO -from 23 -to 0 gpio_n ] + set gpio_p [ create_bd_port -dir IO -from 23 -to 0 gpio_p ] + set hdmi_clk [ create_bd_port -dir O -type clk hdmi_clk ] + set hdmi_d [ create_bd_port -dir O -from 15 -to 0 hdmi_d ] + set hdmi_de [ create_bd_port -dir O hdmi_de ] + set hdmi_hsync [ create_bd_port -dir O hdmi_hsync ] + set hdmi_int [ create_bd_port -dir I hdmi_int ] + set hdmi_spdif [ create_bd_port -dir O hdmi_spdif ] + set hdmi_vsync [ create_bd_port -dir O hdmi_vsync ] + set i2c_scl [ create_bd_port -dir IO i2c_scl ] + set i2c_sda [ create_bd_port -dir IO i2c_sda ] + set rxi_data_n [ create_bd_port -dir I -from 7 -to 0 rxi_data_n ] + set rxi_data_p [ create_bd_port -dir I -from 7 -to 0 rxi_data_p ] + set rxi_frame_n [ create_bd_port -dir I rxi_frame_n ] + set rxi_frame_p [ create_bd_port -dir I rxi_frame_p ] + set rxi_lclk_n [ create_bd_port -dir I rxi_lclk_n ] + set rxi_lclk_p [ create_bd_port -dir I rxi_lclk_p ] + set rxo_rd_wait_n [ create_bd_port -dir O rxo_rd_wait_n ] + set rxo_rd_wait_p [ create_bd_port -dir O rxo_rd_wait_p ] + set rxo_wr_wait_n [ create_bd_port -dir O rxo_wr_wait_n ] + set rxo_wr_wait_p [ create_bd_port -dir O rxo_wr_wait_p ] + set txi_rd_wait_n [ create_bd_port -dir I txi_rd_wait_n ] + set txi_rd_wait_p [ create_bd_port -dir I txi_rd_wait_p ] + set txi_wr_wait_n [ create_bd_port -dir I txi_wr_wait_n ] + set txi_wr_wait_p [ create_bd_port -dir I txi_wr_wait_p ] + set txo_data_n [ create_bd_port -dir O -from 7 -to 0 txo_data_n ] + set txo_data_p [ create_bd_port -dir O -from 7 -to 0 txo_data_p ] + set txo_frame_n [ create_bd_port -dir O txo_frame_n ] + set txo_frame_p [ create_bd_port -dir O txo_frame_p ] + set txo_lclk_n [ create_bd_port -dir O txo_lclk_n ] + set txo_lclk_p [ create_bd_port -dir O txo_lclk_p ] + + # Create instance: axi_hdmi_intercon, and set properties + set axi_hdmi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_hdmi_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {4} \ + ] $axi_hdmi_intercon + + # Create instance: axi_parallella_m_axi_intercon, and set properties + set axi_parallella_m_axi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_m_axi_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + CONFIG.NUM_SI {1} \ + ] $axi_parallella_m_axi_intercon + + # Create instance: axi_parallella_s_axi_intercon, and set properties + set axi_parallella_s_axi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_s_axi_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_parallella_s_axi_intercon + + # Create instance: hdmi_0 + create_hier_cell_hdmi_0 [current_bd_instance .] hdmi_0 + + # Create instance: parallella_base_0, and set properties + set parallella_base_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_base:1.0 parallella_base_0 ] + set_property -dict [ list \ + CONFIG.NGPIO {24} \ + ] $parallella_base_0 + + # Create instance: proc_sys_reset_0, and set properties + set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ] + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {666.666687} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.062893} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {40} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {200000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1333.333} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {53} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {3} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {48} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1600.000} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {4} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x3FFFFFFF} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {EMIO} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {1} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {1} \ + CONFIG.PCW_EN_EMIO_I2C0 {1} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {1} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_SDIO1 {1} \ + CONFIG.PCW_EN_UART1 {1} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {1} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {152} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {64} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {1} \ + CONFIG.PCW_I2C0_GRP_INT_IO {EMIO} \ + CONFIG.PCW_I2C0_I2C0_IO {EMIO} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {30} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {1} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {inout} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {inout} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {in} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {out} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {in} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {inout} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {inout} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {in} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {inout} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {in} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#UART 1#UART 1#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO#GPIO} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#tx#rx#data[0]#cmd#clk#data[1]#data[2]#data[3]#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#gpio[52]#gpio[53]} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {400.000000} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} \ + CONFIG.PCW_UIPARAM_DDR_CL {9} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {9} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {9} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {0} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_USB1_IO {MIO 40 .. 51} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_DMA0 {1} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {1} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {1} \ + CONFIG.PCW_USE_S_AXI_HP0 {1} \ + CONFIG.PCW_USE_S_AXI_HP1 {1} \ + ] $processing_system7_0 + + # Create instance: sys_concat_intc, and set properties + set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ] + set_property -dict [ list \ + CONFIG.NUM_PORTS {16} \ + ] $sys_concat_intc + + # Create interface connections + connect_bd_intf_net -intf_net axi_hdmi_intercon_M00_AXI [get_bd_intf_pins axi_hdmi_intercon/M00_AXI] [get_bd_intf_pins hdmi_0/S_AXI] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M01_AXI [get_bd_intf_pins axi_hdmi_intercon/M01_AXI] [get_bd_intf_pins hdmi_0/S_AXI_LITE] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M02_AXI [get_bd_intf_pins axi_hdmi_intercon/M02_AXI] [get_bd_intf_pins hdmi_0/s_axi1] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M03_AXI [get_bd_intf_pins axi_hdmi_intercon/M03_AXI] [get_bd_intf_pins hdmi_0/s_axi2] + connect_bd_intf_net -intf_net axi_parallella_m_axi_intercon_M00_AXI [get_bd_intf_pins axi_parallella_m_axi_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] + connect_bd_intf_net -intf_net axi_parallella_s_axi_intercon_M00_AXI [get_bd_intf_pins axi_parallella_s_axi_intercon/M00_AXI] [get_bd_intf_pins parallella_base_0/s_axi] + connect_bd_intf_net -intf_net hdmi_0_DMA_REQ [get_bd_intf_pins hdmi_0/DMA_REQ] [get_bd_intf_pins processing_system7_0/DMA0_REQ] + connect_bd_intf_net -intf_net hdmi_0_M00_AXI [get_bd_intf_pins hdmi_0/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP0] + connect_bd_intf_net -intf_net parallella_base_0_m_axi [get_bd_intf_pins axi_parallella_m_axi_intercon/S00_AXI] [get_bd_intf_pins parallella_base_0/m_axi] + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_DMA0_ACK [get_bd_intf_pins hdmi_0/DMA_ACK] [get_bd_intf_pins processing_system7_0/DMA0_ACK] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins axi_hdmi_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP0] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP1 [get_bd_intf_pins axi_parallella_s_axi_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP1] + + # Create port connections + connect_bd_net -net hdmi_0_hdmi_16_data [get_bd_ports hdmi_d] [get_bd_pins hdmi_0/hdmi_16_data] + connect_bd_net -net hdmi_0_hdmi_16_data_e [get_bd_ports hdmi_de] [get_bd_pins hdmi_0/hdmi_16_data_e] + connect_bd_net -net hdmi_0_hdmi_16_hsync [get_bd_ports hdmi_hsync] [get_bd_pins hdmi_0/hdmi_16_hsync] + connect_bd_net -net hdmi_0_hdmi_16_vsync [get_bd_ports hdmi_vsync] [get_bd_pins hdmi_0/hdmi_16_vsync] + connect_bd_net -net hdmi_0_hdmi_out_clk [get_bd_ports hdmi_clk] [get_bd_pins hdmi_0/hdmi_out_clk] + connect_bd_net -net hdmi_0_int [get_bd_ports hdmi_int] [get_bd_pins sys_concat_intc/In14] + connect_bd_net -net hdmi_0_mm2s_introut [get_bd_pins hdmi_0/mm2s_introut] [get_bd_pins sys_concat_intc/In15] + connect_bd_net -net hdmi_0_spdif_tx_o1 [get_bd_ports hdmi_spdif] [get_bd_pins hdmi_0/spdif_tx_o] + connect_bd_net -net parallella_base_0_cclk_n [get_bd_ports cclk_n] [get_bd_pins parallella_base_0/cclk_n] + connect_bd_net -net parallella_base_0_cclk_p [get_bd_ports cclk_p] [get_bd_pins parallella_base_0/cclk_p] + connect_bd_net -net parallella_base_0_chip_resetb [get_bd_ports chip_nreset] [get_bd_pins parallella_base_0/chip_nreset] + connect_bd_net -net parallella_base_0_constant_zero [get_bd_pins parallella_base_0/constant_zero] [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In9] [get_bd_pins sys_concat_intc/In10] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] + connect_bd_net -net parallella_base_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] + connect_bd_net -net parallella_base_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] + connect_bd_net -net parallella_base_0_i2c_scl [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] + connect_bd_net -net parallella_base_0_i2c_scl_i [get_bd_pins parallella_base_0/i2c_scl_i] [get_bd_pins processing_system7_0/I2C0_SCL_I] + connect_bd_net -net parallella_base_0_i2c_sda [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] + connect_bd_net -net parallella_base_0_i2c_sda_i [get_bd_pins parallella_base_0/i2c_sda_i] [get_bd_pins processing_system7_0/I2C0_SDA_I] + connect_bd_net -net parallella_base_0_mailbox_irq [get_bd_pins parallella_base_0/mailbox_irq] [get_bd_pins sys_concat_intc/In11] + connect_bd_net -net parallella_base_0_ps_gpio_i [get_bd_pins parallella_base_0/ps_gpio_i] [get_bd_pins processing_system7_0/GPIO_I] + connect_bd_net -net parallella_base_0_rxo_rd_wait_n [get_bd_ports rxo_rd_wait_n] [get_bd_pins parallella_base_0/rxo_rd_wait_n] + connect_bd_net -net parallella_base_0_rxo_rd_wait_p [get_bd_ports rxo_rd_wait_p] [get_bd_pins parallella_base_0/rxo_rd_wait_p] + connect_bd_net -net parallella_base_0_rxo_wr_wait_n [get_bd_ports rxo_wr_wait_n] [get_bd_pins parallella_base_0/rxo_wr_wait_n] + connect_bd_net -net parallella_base_0_rxo_wr_wait_p [get_bd_ports rxo_wr_wait_p] [get_bd_pins parallella_base_0/rxo_wr_wait_p] + connect_bd_net -net parallella_base_0_txo_data_n [get_bd_ports txo_data_n] [get_bd_pins parallella_base_0/txo_data_n] + connect_bd_net -net parallella_base_0_txo_data_p [get_bd_ports txo_data_p] [get_bd_pins parallella_base_0/txo_data_p] + connect_bd_net -net parallella_base_0_txo_frame_n [get_bd_ports txo_frame_n] [get_bd_pins parallella_base_0/txo_frame_n] + connect_bd_net -net parallella_base_0_txo_frame_p [get_bd_ports txo_frame_p] [get_bd_pins parallella_base_0/txo_frame_p] + connect_bd_net -net parallella_base_0_txo_lclk_n [get_bd_ports txo_lclk_n] [get_bd_pins parallella_base_0/txo_lclk_n] + connect_bd_net -net parallella_base_0_txo_lclk_p [get_bd_ports txo_lclk_p] [get_bd_pins parallella_base_0/txo_lclk_p] + connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins axi_hdmi_intercon/ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/ARESETN] [get_bd_pins proc_sys_reset_0/interconnect_aresetn] + connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins axi_hdmi_intercon/M00_ARESETN] [get_bd_pins axi_hdmi_intercon/M01_ARESETN] [get_bd_pins axi_hdmi_intercon/M02_ARESETN] [get_bd_pins axi_hdmi_intercon/M03_ARESETN] [get_bd_pins axi_hdmi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/M00_ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/M00_ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/S00_ARESETN] [get_bd_pins hdmi_0/axi_resetn] [get_bd_pins parallella_base_0/m_axi_aresetn] [get_bd_pins parallella_base_0/s_axi_aresetn] [get_bd_pins parallella_base_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_hdmi_intercon/ACLK] [get_bd_pins axi_hdmi_intercon/M00_ACLK] [get_bd_pins axi_hdmi_intercon/M01_ACLK] [get_bd_pins axi_hdmi_intercon/M02_ACLK] [get_bd_pins axi_hdmi_intercon/M03_ACLK] [get_bd_pins axi_hdmi_intercon/S00_ACLK] [get_bd_pins axi_parallella_m_axi_intercon/ACLK] [get_bd_pins axi_parallella_m_axi_intercon/M00_ACLK] [get_bd_pins axi_parallella_m_axi_intercon/S00_ACLK] [get_bd_pins axi_parallella_s_axi_intercon/ACLK] [get_bd_pins axi_parallella_s_axi_intercon/M00_ACLK] [get_bd_pins axi_parallella_s_axi_intercon/S00_ACLK] [get_bd_pins hdmi_0/s_axi_aclk] [get_bd_pins parallella_base_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/DMA0_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP1_ACLK] + connect_bd_net -net processing_system7_0_FCLK_CLK2 [get_bd_pins hdmi_0/clk] [get_bd_pins processing_system7_0/FCLK_CLK2] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins proc_sys_reset_0/ext_reset_in] [get_bd_pins processing_system7_0/FCLK_RESET0_N] + connect_bd_net -net processing_system7_0_GPIO_O [get_bd_pins parallella_base_0/ps_gpio_o] [get_bd_pins processing_system7_0/GPIO_O] + connect_bd_net -net processing_system7_0_GPIO_T [get_bd_pins parallella_base_0/ps_gpio_t] [get_bd_pins processing_system7_0/GPIO_T] + connect_bd_net -net processing_system7_0_I2C0_SCL_O [get_bd_pins parallella_base_0/i2c_scl_o] [get_bd_pins processing_system7_0/I2C0_SCL_O] + connect_bd_net -net processing_system7_0_I2C0_SCL_T [get_bd_pins parallella_base_0/i2c_scl_t] [get_bd_pins processing_system7_0/I2C0_SCL_T] + connect_bd_net -net processing_system7_0_I2C0_SDA_O [get_bd_pins parallella_base_0/i2c_sda_o] [get_bd_pins processing_system7_0/I2C0_SDA_O] + connect_bd_net -net processing_system7_0_I2C0_SDA_T [get_bd_pins parallella_base_0/i2c_sda_t] [get_bd_pins processing_system7_0/I2C0_SDA_T] + connect_bd_net -net rxi_data_n_1 [get_bd_ports rxi_data_n] [get_bd_pins parallella_base_0/rxi_data_n] + connect_bd_net -net rxi_data_p_1 [get_bd_ports rxi_data_p] [get_bd_pins parallella_base_0/rxi_data_p] + connect_bd_net -net rxi_frame_n_1 [get_bd_ports rxi_frame_n] [get_bd_pins parallella_base_0/rxi_frame_n] + connect_bd_net -net rxi_frame_p_1 [get_bd_ports rxi_frame_p] [get_bd_pins parallella_base_0/rxi_frame_p] + connect_bd_net -net rxi_lclk_n_1 [get_bd_ports rxi_lclk_n] [get_bd_pins parallella_base_0/rxi_lclk_n] + connect_bd_net -net rxi_lclk_p_1 [get_bd_ports rxi_lclk_p] [get_bd_pins parallella_base_0/rxi_lclk_p] + connect_bd_net -net sys_concat_intc_dout [get_bd_pins processing_system7_0/IRQ_F2P] [get_bd_pins sys_concat_intc/dout] + connect_bd_net -net txi_rd_wait_n_1 [get_bd_ports txi_rd_wait_n] [get_bd_pins parallella_base_0/txi_rd_wait_n] + connect_bd_net -net txi_rd_wait_p_1 [get_bd_ports txi_rd_wait_p] [get_bd_pins parallella_base_0/txi_rd_wait_p] + connect_bd_net -net txi_wr_wait_n_1 [get_bd_ports txi_wr_wait_n] [get_bd_pins parallella_base_0/txi_wr_wait_n] + connect_bd_net -net txi_wr_wait_p_1 [get_bd_ports txi_wr_wait_p] [get_bd_pins parallella_base_0/txi_wr_wait_p] + + # Create address segments + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM + create_bd_addr_seg -range 0x00010000 -offset 0x66000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_clkgen_0/s_axi/axi_lite] SEG_axi_clkgen_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x6C000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_hdmi_tx_0/s_axi/axi_lite] SEG_axi_hdmi_tx_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x75C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_spdif_tx_0/s_axi/axi_lite] SEG_axi_spdif_tx_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_vdma_0/S_AXI_LITE/Reg] SEG_axi_vdma_0_Reg + create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_vdma_0/Data_MM2S] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl new file mode 100644 index 00000000..0984b25a --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl @@ -0,0 +1,28 @@ + +#Design name ("system" recommended) +set design system + +#Project directory ("." recommended) +set projdir ./ + +#Device name +set partname "xc7z020clg400-1" + +#Paths to all IP blocks to use in Vivado "system.bd" + +set ip_repos [list "../parallella_base" "../../../../../parallella-fpga/AdiHDLLib/library"] + +#All source files +set hdl_files [] + +#All constraints files +set constraints_files [list \ + ../parallella_timing.xdc \ + ../parallella_io.xdc \ + ../parallella_7020_io.xdc \ + ] + +########################################################### +# PREPARE FOR SYNTHESIS +########################################################### +set oh_verilog_define "CFG_ASIC=0 CFG_PLATFORM=\"ZYNQ\"" From 00fa7f89227be941f8c35e007b35d9c876639b12 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 13:10:23 -0400 Subject: [PATCH 12/30] ip: fifo_async_104x32: Use GLOBAL synthesis flow Use parallella-fgpa version. IIRC oh master doesn't synthesize the headless block designs correctly. But the parallella-fpga project HDMI projects does work with parallella-base from oh. This is the most likely culprit I can come up with, but I haven't tested it yet. --- src/xilibs/ip/fifo_async_104x32.xci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xilibs/ip/fifo_async_104x32.xci b/src/xilibs/ip/fifo_async_104x32.xci index 11ca18ad..c146c789 100644 --- a/src/xilibs/ip/fifo_async_104x32.xci +++ b/src/xilibs/ip/fifo_async_104x32.xci @@ -503,7 +503,7 @@ . 2018.2.2 - OUT_OF_CONTEXT + GLOBAL From 86e4eba0fdeaa4d5239881764c7a0e63ac0ea4b2 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 13:16:55 -0400 Subject: [PATCH 13/30] parallella/fpga: Use same net names across block designs --- src/parallella/fpga/headless_e16_z7010/system_bd.tcl | 8 ++++---- src/parallella/fpga/headless_e16_z7020/system_bd.tcl | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl index cff1628a..c9e0e28c 100644 --- a/src/parallella/fpga/headless_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7010/system_bd.tcl @@ -662,15 +662,15 @@ proc create_root_design { parentCell } { connect_bd_intf_net -intf_net processing_system7_0_axi_periph_M00_AXI [get_bd_intf_pins parallella_base_0/s_axi] [get_bd_intf_pins processing_system7_0_axi_periph/M00_AXI] # Create port connections - connect_bd_net -net Net [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] - connect_bd_net -net Net1 [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] - connect_bd_net -net Net2 [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] - connect_bd_net -net Net3 [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] connect_bd_net -net parallella_base_0_cclk_n [get_bd_ports cclk_n] [get_bd_pins parallella_base_0/cclk_n] connect_bd_net -net parallella_base_0_cclk_p [get_bd_ports cclk_p] [get_bd_pins parallella_base_0/cclk_p] connect_bd_net -net parallella_base_0_chip_resetb [get_bd_ports chip_nreset] [get_bd_pins parallella_base_0/chip_nreset] connect_bd_net -net parallella_base_0_constant_zero [get_bd_pins parallella_base_0/constant_zero] [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In9] [get_bd_pins sys_concat_intc/In10] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] [get_bd_pins sys_concat_intc/In14] [get_bd_pins sys_concat_intc/In15] + connect_bd_net -net parallella_base_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] + connect_bd_net -net parallella_base_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] + connect_bd_net -net parallella_base_0_i2c_scl [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] connect_bd_net -net parallella_base_0_i2c_scl_i [get_bd_pins parallella_base_0/i2c_scl_i] [get_bd_pins processing_system7_0/I2C0_SCL_I] + connect_bd_net -net parallella_base_0_i2c_sda [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] connect_bd_net -net parallella_base_0_i2c_sda_i [get_bd_pins parallella_base_0/i2c_sda_i] [get_bd_pins processing_system7_0/I2C0_SDA_I] connect_bd_net -net parallella_base_0_mailbox_irq [get_bd_pins parallella_base_0/mailbox_irq] [get_bd_pins sys_concat_intc/In11] connect_bd_net -net parallella_base_0_ps_gpio_i [get_bd_pins parallella_base_0/ps_gpio_i] [get_bd_pins processing_system7_0/GPIO_I] diff --git a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl index 9ab45f6c..c9e4d976 100644 --- a/src/parallella/fpga/headless_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/headless_e16_z7020/system_bd.tcl @@ -662,15 +662,15 @@ proc create_root_design { parentCell } { connect_bd_intf_net -intf_net processing_system7_0_axi_periph_M00_AXI [get_bd_intf_pins parallella_base_0/s_axi] [get_bd_intf_pins processing_system7_0_axi_periph/M00_AXI] # Create port connections - connect_bd_net -net Net [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] - connect_bd_net -net Net1 [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] - connect_bd_net -net Net2 [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] - connect_bd_net -net Net3 [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] connect_bd_net -net parallella_base_0_cclk_n [get_bd_ports cclk_n] [get_bd_pins parallella_base_0/cclk_n] connect_bd_net -net parallella_base_0_cclk_p [get_bd_ports cclk_p] [get_bd_pins parallella_base_0/cclk_p] connect_bd_net -net parallella_base_0_chip_resetb [get_bd_ports chip_nreset] [get_bd_pins parallella_base_0/chip_nreset] connect_bd_net -net parallella_base_0_constant_zero [get_bd_pins parallella_base_0/constant_zero] [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In9] [get_bd_pins sys_concat_intc/In10] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] [get_bd_pins sys_concat_intc/In14] [get_bd_pins sys_concat_intc/In15] + connect_bd_net -net parallella_base_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] + connect_bd_net -net parallella_base_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] + connect_bd_net -net parallella_base_0_i2c_scl [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] connect_bd_net -net parallella_base_0_i2c_scl_i [get_bd_pins parallella_base_0/i2c_scl_i] [get_bd_pins processing_system7_0/I2C0_SCL_I] + connect_bd_net -net parallella_base_0_i2c_sda [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] connect_bd_net -net parallella_base_0_i2c_sda_i [get_bd_pins parallella_base_0/i2c_sda_i] [get_bd_pins processing_system7_0/I2C0_SDA_I] connect_bd_net -net parallella_base_0_mailbox_irq [get_bd_pins parallella_base_0/mailbox_irq] [get_bd_pins sys_concat_intc/In11] connect_bd_net -net parallella_base_0_ps_gpio_i [get_bd_pins parallella_base_0/ps_gpio_i] [get_bd_pins processing_system7_0/GPIO_I] From b3785c4ce2d358b91e3fe94e88ad65fd436314f7 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 13:46:55 -0400 Subject: [PATCH 14/30] adi: Import ADI HDL IP:s needed by HDMI designs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Import: https://github.com/analogdevicesinc/hdl.git Branch: hdl_2018_r2 Commit: 28df7548b002cf7201ed291a85edfa7643b5f52b These directories preseved, the rest was pruned: . ├── library │   ├── altera │   │   └── common │   │   ├── alt_ifconv │   │   ├── alt_mem_asym │   │   ├── alt_mul │   │   └── alt_serdes │   ├── axi_clkgen │   │   └── bd │   ├── axi_hdmi_tx │   ├── axi_spdif_tx │   ├── common │   ├── scripts │   └── xilinx │   └── common └── projects └── scripts --- src/adi/hdl/.gitattributes | 15 + src/adi/hdl/.gitignore | 79 ++ src/adi/hdl/LICENSE | 57 ++ src/adi/hdl/LICENSE_ADIBSD | 33 + src/adi/hdl/LICENSE_GPL2 | 310 +++++++ src/adi/hdl/LICENSE_LGPL | 152 ++++ src/adi/hdl/Makefile | 50 ++ src/adi/hdl/README.md | 72 ++ src/adi/hdl/library/Makefile | 227 +++++ .../hdl/library/altera/common/ad_dcfilter.v | 85 ++ src/adi/hdl/library/altera/common/ad_mul.v | 90 ++ .../library/altera/common/alt_ifconv/Makefile | 11 + .../altera/common/alt_ifconv/alt_ifconv.v | 60 ++ .../common/alt_ifconv/alt_ifconv_hw.tcl | 34 + .../altera/common/alt_mem_asym/Makefile | 10 + .../common/alt_mem_asym/alt_mem_asym_hw.tcl | 49 + .../library/altera/common/alt_mul/Makefile | 10 + .../altera/common/alt_mul/alt_mul_hw.tcl | 35 + .../library/altera/common/alt_serdes/Makefile | 10 + .../common/alt_serdes/alt_serdes_hw.tcl | 132 +++ .../altera/common/up_clock_mon_constr.sdc | 4 + .../library/altera/common/up_rst_constr.sdc | 4 + .../altera/common/up_xfer_cntrl_constr.sdc | 4 + .../altera/common/up_xfer_status_constr.sdc | 4 + src/adi/hdl/library/axi_clkgen/Makefile | 17 + src/adi/hdl/library/axi_clkgen/axi_clkgen.v | 215 +++++ .../hdl/library/axi_clkgen/axi_clkgen_ip.tcl | 52 ++ src/adi/hdl/library/axi_clkgen/bd/bd.tcl | 75 ++ src/adi/hdl/library/axi_hdmi_tx/Makefile | 41 + src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx.v | 342 +++++++ .../axi_hdmi_tx/axi_hdmi_tx_constr.sdc | 10 + .../axi_hdmi_tx/axi_hdmi_tx_constr.xdc | 10 + .../library/axi_hdmi_tx/axi_hdmi_tx_core.v | 572 ++++++++++++ .../hdl/library/axi_hdmi_tx/axi_hdmi_tx_es.v | 107 +++ .../library/axi_hdmi_tx/axi_hdmi_tx_hw.tcl | 104 +++ .../library/axi_hdmi_tx/axi_hdmi_tx_ip.tcl | 72 ++ .../library/axi_hdmi_tx/axi_hdmi_tx_vdma.v | 235 +++++ src/adi/hdl/library/axi_spdif_tx/Makefile | 19 + .../hdl/library/axi_spdif_tx/axi_spdif_tx.vhd | 318 +++++++ .../axi_spdif_tx/axi_spdif_tx_constr.xdc | 11 + .../library/axi_spdif_tx/axi_spdif_tx_ip.tcl | 50 ++ .../hdl/library/axi_spdif_tx/tx_encoder.vhd | 495 +++++++++++ .../hdl/library/axi_spdif_tx/tx_package.vhd | 88 ++ src/adi/hdl/library/common/ad_addsub.v | 115 +++ src/adi/hdl/library/common/ad_adl5904_rst.v | 78 ++ src/adi/hdl/library/common/ad_axis_inf_rx.v | 193 ++++ src/adi/hdl/library/common/ad_b2g.v | 59 ++ src/adi/hdl/library/common/ad_csc_1.v | 115 +++ src/adi/hdl/library/common/ad_csc_1_add.v | 147 +++ src/adi/hdl/library/common/ad_csc_1_mul.v | 97 ++ src/adi/hdl/library/common/ad_csc_CrYCb2RGB.v | 103 +++ src/adi/hdl/library/common/ad_csc_RGB2CrYCb.v | 103 +++ src/adi/hdl/library/common/ad_datafmt.v | 108 +++ src/adi/hdl/library/common/ad_dds.v | 132 +++ src/adi/hdl/library/common/ad_dds_1.v | 115 +++ src/adi/hdl/library/common/ad_dds_2.v | 156 ++++ .../hdl/library/common/ad_dds_cordic_pipe.v | 100 +++ src/adi/hdl/library/common/ad_dds_sine.v | 206 +++++ .../hdl/library/common/ad_dds_sine_cordic.v | 430 +++++++++ src/adi/hdl/library/common/ad_edge_detect.v | 83 ++ src/adi/hdl/library/common/ad_g2b.v | 59 ++ src/adi/hdl/library/common/ad_iqcor.v | 183 ++++ src/adi/hdl/library/common/ad_mem.v | 71 ++ src/adi/hdl/library/common/ad_mem_asym.v | 148 ++++ .../hdl/library/common/ad_perfect_shuffle.v | 68 ++ src/adi/hdl/library/common/ad_pnmon.v | 106 +++ src/adi/hdl/library/common/ad_pps_receiver.v | 130 +++ .../common/ad_pps_receiver_constr.ttcl | 20 + src/adi/hdl/library/common/ad_rst.v | 77 ++ src/adi/hdl/library/common/ad_ss_422to444.v | 138 +++ src/adi/hdl/library/common/ad_ss_444to422.v | 134 +++ src/adi/hdl/library/common/ad_sysref_gen.v | 85 ++ src/adi/hdl/library/common/ad_tdd_control.v | 834 ++++++++++++++++++ src/adi/hdl/library/common/ad_xcvr_rx_if.v | 80 ++ src/adi/hdl/library/common/axi_ctrlif.vhd | 148 ++++ .../common/axi_streaming_dma_rx_fifo.vhd | 117 +++ .../common/axi_streaming_dma_tx_fifo.vhd | 111 +++ src/adi/hdl/library/common/dma_fifo.vhd | 112 +++ src/adi/hdl/library/common/pl330_dma_fifo.vhd | 175 ++++ src/adi/hdl/library/common/up_adc_channel.v | 491 +++++++++++ src/adi/hdl/library/common/up_adc_common.v | 454 ++++++++++ src/adi/hdl/library/common/up_axi.v | 243 +++++ src/adi/hdl/library/common/up_clkgen.v | 184 ++++ src/adi/hdl/library/common/up_clock_mon.v | 146 +++ src/adi/hdl/library/common/up_dac_channel.v | 430 +++++++++ src/adi/hdl/library/common/up_dac_common.v | 479 ++++++++++ src/adi/hdl/library/common/up_delay_cntrl.v | 218 +++++ src/adi/hdl/library/common/up_hdmi_rx.v | 286 ++++++ src/adi/hdl/library/common/up_hdmi_tx.v | 350 ++++++++ src/adi/hdl/library/common/up_pmod.v | 136 +++ src/adi/hdl/library/common/up_tdd_cntrl.v | 444 ++++++++++ src/adi/hdl/library/common/up_xfer_cntrl.v | 126 +++ src/adi/hdl/library/common/up_xfer_status.v | 128 +++ .../hdl/library/common/util_axis_upscale.v | 98 ++ src/adi/hdl/library/common/util_delay.v | 74 ++ src/adi/hdl/library/common/util_pulse_gen.v | 93 ++ src/adi/hdl/library/scripts/adi_env.tcl | 15 + src/adi/hdl/library/scripts/adi_ip.tcl | 368 ++++++++ src/adi/hdl/library/scripts/adi_ip_alt.tcl | 249 ++++++ src/adi/hdl/library/scripts/library.mk | 78 ++ .../hdl/library/xilinx/common/ad_data_clk.v | 84 ++ .../hdl/library/xilinx/common/ad_data_in.v | 214 +++++ .../hdl/library/xilinx/common/ad_data_out.v | 181 ++++ .../hdl/library/xilinx/common/ad_dcfilter.v | 197 +++++ src/adi/hdl/library/xilinx/common/ad_iobuf.v | 59 ++ .../hdl/library/xilinx/common/ad_mmcm_drp.v | 253 ++++++ src/adi/hdl/library/xilinx/common/ad_mul.v | 85 ++ .../library/xilinx/common/ad_rst_constr.xdc | 8 + .../hdl/library/xilinx/common/ad_serdes_clk.v | 160 ++++ .../hdl/library/xilinx/common/ad_serdes_in.v | 197 +++++ .../hdl/library/xilinx/common/ad_serdes_out.v | 133 +++ .../xilinx/common/up_clock_mon_constr.xdc | 8 + .../xilinx/common/up_xfer_cntrl_constr.xdc | 7 + .../xilinx/common/up_xfer_status_constr.xdc | 7 + src/adi/hdl/projects/scripts/adi_board.tcl | 763 ++++++++++++++++ src/adi/hdl/projects/scripts/adi_env.tcl | 15 + src/adi/hdl/projects/scripts/adi_project.tcl | 289 ++++++ .../hdl/projects/scripts/adi_project_alt.tcl | 156 ++++ src/adi/hdl/projects/scripts/adi_tquest.tcl | 41 + .../hdl/projects/scripts/adi_xilinx_msg.tcl | 107 +++ .../hdl/projects/scripts/project-altera.mk | 86 ++ .../hdl/projects/scripts/project-toplevel.mk | 24 + .../hdl/projects/scripts/project-xilinx.mk | 62 ++ src/adi/hdl/quiet.mk | 52 ++ 124 files changed, 17784 insertions(+) create mode 100644 src/adi/hdl/.gitattributes create mode 100644 src/adi/hdl/.gitignore create mode 100644 src/adi/hdl/LICENSE create mode 100644 src/adi/hdl/LICENSE_ADIBSD create mode 100644 src/adi/hdl/LICENSE_GPL2 create mode 100644 src/adi/hdl/LICENSE_LGPL create mode 100644 src/adi/hdl/Makefile create mode 100644 src/adi/hdl/README.md create mode 100644 src/adi/hdl/library/Makefile create mode 100644 src/adi/hdl/library/altera/common/ad_dcfilter.v create mode 100644 src/adi/hdl/library/altera/common/ad_mul.v create mode 100644 src/adi/hdl/library/altera/common/alt_ifconv/Makefile create mode 100644 src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv.v create mode 100644 src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv_hw.tcl create mode 100644 src/adi/hdl/library/altera/common/alt_mem_asym/Makefile create mode 100644 src/adi/hdl/library/altera/common/alt_mem_asym/alt_mem_asym_hw.tcl create mode 100644 src/adi/hdl/library/altera/common/alt_mul/Makefile create mode 100644 src/adi/hdl/library/altera/common/alt_mul/alt_mul_hw.tcl create mode 100644 src/adi/hdl/library/altera/common/alt_serdes/Makefile create mode 100644 src/adi/hdl/library/altera/common/alt_serdes/alt_serdes_hw.tcl create mode 100644 src/adi/hdl/library/altera/common/up_clock_mon_constr.sdc create mode 100644 src/adi/hdl/library/altera/common/up_rst_constr.sdc create mode 100644 src/adi/hdl/library/altera/common/up_xfer_cntrl_constr.sdc create mode 100644 src/adi/hdl/library/altera/common/up_xfer_status_constr.sdc create mode 100644 src/adi/hdl/library/axi_clkgen/Makefile create mode 100644 src/adi/hdl/library/axi_clkgen/axi_clkgen.v create mode 100644 src/adi/hdl/library/axi_clkgen/axi_clkgen_ip.tcl create mode 100644 src/adi/hdl/library/axi_clkgen/bd/bd.tcl create mode 100644 src/adi/hdl/library/axi_hdmi_tx/Makefile create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx.v create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.sdc create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.xdc create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_core.v create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_es.v create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_hw.tcl create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_ip.tcl create mode 100644 src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_vdma.v create mode 100644 src/adi/hdl/library/axi_spdif_tx/Makefile create mode 100644 src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx.vhd create mode 100644 src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_constr.xdc create mode 100644 src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_ip.tcl create mode 100644 src/adi/hdl/library/axi_spdif_tx/tx_encoder.vhd create mode 100644 src/adi/hdl/library/axi_spdif_tx/tx_package.vhd create mode 100644 src/adi/hdl/library/common/ad_addsub.v create mode 100644 src/adi/hdl/library/common/ad_adl5904_rst.v create mode 100644 src/adi/hdl/library/common/ad_axis_inf_rx.v create mode 100644 src/adi/hdl/library/common/ad_b2g.v create mode 100644 src/adi/hdl/library/common/ad_csc_1.v create mode 100644 src/adi/hdl/library/common/ad_csc_1_add.v create mode 100644 src/adi/hdl/library/common/ad_csc_1_mul.v create mode 100644 src/adi/hdl/library/common/ad_csc_CrYCb2RGB.v create mode 100644 src/adi/hdl/library/common/ad_csc_RGB2CrYCb.v create mode 100644 src/adi/hdl/library/common/ad_datafmt.v create mode 100644 src/adi/hdl/library/common/ad_dds.v create mode 100644 src/adi/hdl/library/common/ad_dds_1.v create mode 100644 src/adi/hdl/library/common/ad_dds_2.v create mode 100644 src/adi/hdl/library/common/ad_dds_cordic_pipe.v create mode 100644 src/adi/hdl/library/common/ad_dds_sine.v create mode 100644 src/adi/hdl/library/common/ad_dds_sine_cordic.v create mode 100644 src/adi/hdl/library/common/ad_edge_detect.v create mode 100644 src/adi/hdl/library/common/ad_g2b.v create mode 100644 src/adi/hdl/library/common/ad_iqcor.v create mode 100644 src/adi/hdl/library/common/ad_mem.v create mode 100644 src/adi/hdl/library/common/ad_mem_asym.v create mode 100644 src/adi/hdl/library/common/ad_perfect_shuffle.v create mode 100644 src/adi/hdl/library/common/ad_pnmon.v create mode 100644 src/adi/hdl/library/common/ad_pps_receiver.v create mode 100644 src/adi/hdl/library/common/ad_pps_receiver_constr.ttcl create mode 100644 src/adi/hdl/library/common/ad_rst.v create mode 100644 src/adi/hdl/library/common/ad_ss_422to444.v create mode 100644 src/adi/hdl/library/common/ad_ss_444to422.v create mode 100644 src/adi/hdl/library/common/ad_sysref_gen.v create mode 100644 src/adi/hdl/library/common/ad_tdd_control.v create mode 100644 src/adi/hdl/library/common/ad_xcvr_rx_if.v create mode 100644 src/adi/hdl/library/common/axi_ctrlif.vhd create mode 100644 src/adi/hdl/library/common/axi_streaming_dma_rx_fifo.vhd create mode 100644 src/adi/hdl/library/common/axi_streaming_dma_tx_fifo.vhd create mode 100644 src/adi/hdl/library/common/dma_fifo.vhd create mode 100644 src/adi/hdl/library/common/pl330_dma_fifo.vhd create mode 100644 src/adi/hdl/library/common/up_adc_channel.v create mode 100644 src/adi/hdl/library/common/up_adc_common.v create mode 100644 src/adi/hdl/library/common/up_axi.v create mode 100644 src/adi/hdl/library/common/up_clkgen.v create mode 100644 src/adi/hdl/library/common/up_clock_mon.v create mode 100644 src/adi/hdl/library/common/up_dac_channel.v create mode 100644 src/adi/hdl/library/common/up_dac_common.v create mode 100644 src/adi/hdl/library/common/up_delay_cntrl.v create mode 100644 src/adi/hdl/library/common/up_hdmi_rx.v create mode 100644 src/adi/hdl/library/common/up_hdmi_tx.v create mode 100644 src/adi/hdl/library/common/up_pmod.v create mode 100644 src/adi/hdl/library/common/up_tdd_cntrl.v create mode 100644 src/adi/hdl/library/common/up_xfer_cntrl.v create mode 100644 src/adi/hdl/library/common/up_xfer_status.v create mode 100644 src/adi/hdl/library/common/util_axis_upscale.v create mode 100644 src/adi/hdl/library/common/util_delay.v create mode 100644 src/adi/hdl/library/common/util_pulse_gen.v create mode 100644 src/adi/hdl/library/scripts/adi_env.tcl create mode 100644 src/adi/hdl/library/scripts/adi_ip.tcl create mode 100644 src/adi/hdl/library/scripts/adi_ip_alt.tcl create mode 100644 src/adi/hdl/library/scripts/library.mk create mode 100644 src/adi/hdl/library/xilinx/common/ad_data_clk.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_data_in.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_data_out.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_dcfilter.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_iobuf.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_mmcm_drp.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_mul.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_rst_constr.xdc create mode 100644 src/adi/hdl/library/xilinx/common/ad_serdes_clk.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_serdes_in.v create mode 100644 src/adi/hdl/library/xilinx/common/ad_serdes_out.v create mode 100644 src/adi/hdl/library/xilinx/common/up_clock_mon_constr.xdc create mode 100644 src/adi/hdl/library/xilinx/common/up_xfer_cntrl_constr.xdc create mode 100644 src/adi/hdl/library/xilinx/common/up_xfer_status_constr.xdc create mode 100644 src/adi/hdl/projects/scripts/adi_board.tcl create mode 100644 src/adi/hdl/projects/scripts/adi_env.tcl create mode 100644 src/adi/hdl/projects/scripts/adi_project.tcl create mode 100644 src/adi/hdl/projects/scripts/adi_project_alt.tcl create mode 100644 src/adi/hdl/projects/scripts/adi_tquest.tcl create mode 100644 src/adi/hdl/projects/scripts/adi_xilinx_msg.tcl create mode 100644 src/adi/hdl/projects/scripts/project-altera.mk create mode 100644 src/adi/hdl/projects/scripts/project-toplevel.mk create mode 100644 src/adi/hdl/projects/scripts/project-xilinx.mk create mode 100644 src/adi/hdl/quiet.mk diff --git a/src/adi/hdl/.gitattributes b/src/adi/hdl/.gitattributes new file mode 100644 index 00000000..96ff5a1f --- /dev/null +++ b/src/adi/hdl/.gitattributes @@ -0,0 +1,15 @@ +* text=auto + +*.c text +*.h text +*.prj +*.tcl text +*.txt text +*.ucf text +*.v text +*.vhd text +*.xdc text +*.xml text +*.qsys text +*.xise text +Makefile text diff --git a/src/adi/hdl/.gitignore b/src/adi/hdl/.gitignore new file mode 100644 index 00000000..052d4076 --- /dev/null +++ b/src/adi/hdl/.gitignore @@ -0,0 +1,79 @@ +*.cache +*.data +*.xpr +*.log +*.bld +*.chk +*.cmd_log +*.cxt +*.gise +*.gyd +*.jed +*.lso +*.mfd +*.nga +*.ngc +*.ngd +*.ngr +*.pad +*.pnx +*.prj +*.rpt +*.stx +*.syr +*.tim +*.tspec +*.vm6 +*.xst +*.html +*.xrpt +*.err +*_html +*.sld +*.txt +*.qsys +*.csv +xst +netgen +iseconfig +xlnx_auto* +_ngo +_xmsgs +component.xml +*.jou +xgui +*.runs +*.srcs +*.sdk +.Xil +*_INFO.txt +*_dump.txt +db +*.asm.rpt +*.done +*.eda.rpt +*.fit.* +*.map.* +*.sta.* +*.qsf +*.qpf +*.qws +*.sof +*.rbf +system_qsys_script.tcl +hc_output +hps_isw_handoff +hps_sdram_*.csv +incremental_db +system_bd/ +reconfig_mif +*.sopcinfo +*.jdi +*.pin +*.os +*webtalk* +*.xml +*.hw +gui +.timestamp_altera + diff --git a/src/adi/hdl/LICENSE b/src/adi/hdl/LICENSE new file mode 100644 index 00000000..731f5fdf --- /dev/null +++ b/src/adi/hdl/LICENSE @@ -0,0 +1,57 @@ + +In this HDL repository, there are many different and unique modules, consisting +of various HDL (Verilog or VHDL) components. The individual modules are +developed independently, and may be accompanied by separate and unique license +terms (such as GPL, LGPL, BSD, modified BSD, commercial or others). Your license +rights with respect to individual modules accompanied by separate license terms +are defined by those terms. The license agreement for each module is generally +located in the module source code. Nothing else shall restrict, limit, or +otherwise affect any rights or obligations you may have, or conditions to which +you may be subject, under such license terms. This agreement does not limit your +rights under, or grant you rights that supersede, the license terms of any +particular module. + +The mere aggregation of these modules (putting them side by side in the same +source code repository or on a hard disk) does not mean that there is one master +license for all the files. It is up to you, the user, to ensure that during the +building a project, which combines these modules together so that they form a +bit file (either one, or multiple for partial reconfiguration), all the individual +licenses are compatible. For example, if a single module is covered by the GPL, +the whole combination must also be released under the GPL. If you can't, or +won't, do that, you may not distribute the resulting bit file. + +The majority of ADI created modules are dual-licensed, allowing the user to pick +which license they want to use, (and the rights and obligations they have). + - The ADI BSD license, which allows you to make bit files, and not release your + source, as long as it attaches to an ADI device. This is not truly open + source, since it does place extra restrictions on developers. + - The GPL v2 license, which allows you to make bit files, but you must release + all other HDL (except vendor produced, which we consider as a run-time library), + permitted by GPL section 3, along with your bit file. This is truly open + source, and places no additional restrictions on use or fields of endeavor. The + GPL is ideal for use cases such as open source projects with open source + distribution, student/academic purposes, hobby projects, internal research + projects without external distribution, or other projects where all GPL + obligations can be met. + +In these cases, support is handled via web (https://ez.analog.com/community/fpga), +on a best effort basis. Note that our best efforts may not match your product +development schedule. This is a free, non-deterministic support, and is not meant +as a replacement for professional services. However, if this is not adequate +for your needs, or you require support within a specific time frame we recommend +you seek alternatives including seeking professional service and/or commercial/deterministic +support. + +There are also specific modules which are only single-licensed, as listed +below. This list may not be complete, it's up to the user to check each module +license. + - SPDIF, which is released under the LGPL license only. See + https://opencores.org/project,spdif_interface for support. + - The ADI created JESD Core, which is released under the GPL and a commercial + license only. + + The commercial license gives you the full rights to create and distribute + bit files on your own terms without any open source license obligations, + and special avenues for support may be possible. If you are interested + in such a license, contact us at jesd204-licensing@analog.com for more + information. + diff --git a/src/adi/hdl/LICENSE_ADIBSD b/src/adi/hdl/LICENSE_ADIBSD new file mode 100644 index 00000000..b7901834 --- /dev/null +++ b/src/adi/hdl/LICENSE_ADIBSD @@ -0,0 +1,33 @@ + +Copyright 2011(c) Analog Devices, Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + - Neither the name of Analog Devices, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + - The use of this software may or may not infringe the patent rights + of one or more patent holders. This license does not release you + from the requirement that you obtain separate licenses from these + patent holders to use this software. + - Use of the software either in source or binary form, must be run + on or directly connected to an Analog Devices Inc. component. + +THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. + +IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +RIGHTS, 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. diff --git a/src/adi/hdl/LICENSE_GPL2 b/src/adi/hdl/LICENSE_GPL2 new file mode 100644 index 00000000..d81184bb --- /dev/null +++ b/src/adi/hdl/LICENSE_GPL2 @@ -0,0 +1,310 @@ + GNU GENERAL PUBLIC LICENSE + + Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, +Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + + Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to most +of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you can +do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a +fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer +you this license which gives you legal permission to copy, distribute and/or +modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced by +others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish +to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's free +use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program or +work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included without +limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is not +restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and appropriately +publish on each copy an appropriate copyright notice and disclaimer of warranty; +keep intact all the notices that refer to this License and to the absence of any +warranty; and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at +your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating that +you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or +in part contains or is derived from the Program or any part thereof, to be +licensed as a whole at no charge to all third parties under the terms of this +License. + + c) If the modified program normally reads commands interactively when run, +you must cause it, when started running for such interactive use in the most +ordinary way, to print or display an announcement including an appropriate +copyright notice and a notice that there is no warranty (or else, saying that +you provide a warranty) and that users may redistribute the program under these +conditions, and telling the user how to view a copy of this License. (Exception: +if the Program itself is interactive but does not normally print such an +announcement, your work based on the Program is not required to print an +announcement.) These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, and can be +reasonably considered independent and separate works in themselves, then this +License, and its terms, do not apply to those sections when you distribute them +as separate works. But when you distribute the same sections as part of a whole +which is a work based on the Program, the distribution of the whole must be on +the terms of this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on the +Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under Section +2) in object code or executable form under the terms of Sections 1 and 2 above +provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source +code, which must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to +give any third party, for a charge no more than your cost of physically +performing source distribution, a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of Sections 1 and 2 +above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to +distribute corresponding source code. (This alternative is allowed only for +noncommercial distribution and only if you received the program in object code +or executable form with such an offer, in accord with Subsection b above.) The +source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all the +source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code distributed +need not include anything that is normally distributed (in either source or +binary form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component itself +accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source code +from the same place counts as distribution of the source code, even though third +parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or any +work based on the Program), you indicate your acceptance of this License to do +so, and all its terms and conditions for copying, distributing or modifying the +Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by third +parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement +or for any other reason (not limited to patent issues), conditions are imposed +on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of this +License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as a +consequence you may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by all those +who receive copies directly or indirectly through you, then the only way you +could satisfy both it and this License would be to refrain entirely from +distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and the +section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In such +case, this License incorporates the limitation as if written in the body of this +License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Program does not specify a version number of this License, you may choose any +version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + + NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE +PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED +IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS +IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, +SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY +TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF +THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use +to the public, the best way to achieve this is to make it free software which +everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + +one line to give the program's name and an idea of what it does. Copyright (C) +yyyy name of author + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how +to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with +ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and +you are welcome to redistribute it under certain conditions; type `show c' for +details. The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the commands you use +may be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here is +a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program +`Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General +Public License does not permit incorporating your program into proprietary +programs. If your program is a subroutine library, you may consider it more +useful to permit linking proprietary applications with the library. If this is +what you want to do, use the GNU Lesser General Public License instead of this +License. diff --git a/src/adi/hdl/LICENSE_LGPL b/src/adi/hdl/LICENSE_LGPL new file mode 100644 index 00000000..aebcbdd7 --- /dev/null +++ b/src/adi/hdl/LICENSE_LGPL @@ -0,0 +1,152 @@ + GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is +permitted to copy and distribute verbatim copies of this license document, but +changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates the terms +and conditions of version 3 of the GNU General Public License, supplemented by +the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser General +Public License, and the "GNU GPL" refers to version 3 of the GNU General Public +License. + + "The Library" refers to a covered work governed by this License, other than an +Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided by the +Library, but which is not otherwise based on the Library. Defining a subclass +of a class defined by the Library is deemed a mode of using an interface +provided by the Library. + + A "Combined Work" is a work produced by combining or linking an Application +with the Library. The particular version of the Library with which the Combined +Work was made is also called the "Linked Version". + + The "Minimal Corresponding Source" for a Combined Work means the Corresponding +Source for the Combined Work, excluding any source code for portions of the +Combined Work that, considered in isolation, are based on the Application, and +not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the object code +and/or source code for the Application, including any data and utility programs +needed for reproducing the Combined Work from the Application, but excluding the +System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License without +being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a facility +refers to a function or data to be supplied by an Application that uses the +facility (other than as an argument passed when the facility is invoked), then +you may convey a copy of the modified version: + + a) under this License, provided that you make a good faith effort to ensure +that, in the event an Application does not supply the function or data, the +facility still operates, and performs whatever part of its purpose remains +meaningful, or + + b) under the GNU GPL, with none of the additional permissions of this License +applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from a header +file that is part of the Library. You may convey such object code under terms +of your choice, provided that, if the incorporated material is not limited to +numerical parameters, data structure layouts and accessors, or small macros, +inline functions and templates (ten or fewer lines in length), you do both of +the following: + + a) Give prominent notice with each copy of the object code that the Library +is used in it and that the Library and its use are covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license +document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of the +Library contained in the Combined Work and reverse engineering for debugging +such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that the Library +is used in it and that the Library and its use are covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license +document. + + c) For a Combined Work that displays copyright notices during execution, +include the copyright notice for the Library among these notices, as well as a +reference directing the user to the copies of the GNU GPL and this license +document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this +License, and the Corresponding Application Code in a form suitable for, and +under terms that permit, the user to recombine or relink the Application with a +modified version of the Linked Version to produce a modified Combined Work, in +the manner specified by section 6 of the GNU GPL for conveying Corresponding +Source. + + 1) Use a suitable shared library mechanism for linking with the Library. +A suitable mechanism is one that (a) uses at run time a copy of the Library +already present on the user's computer system, and (b) will operate properly +with a modified version of the Library that is interface-compatible with the +Linked Version. + + e) Provide Installation Information, but only if you would otherwise be +required to provide such information under section 6 of the GNU GPL, and only to +the extent that such information is necessary to install and execute a modified +version of the Combined Work produced by recombining or relinking the +Application with a modified version of the Linked Version. (If you use option +4d0, the Installation Information must accompany the Minimal Corresponding +Source and Corresponding Application Code. If you use option 4d1, you must +provide the Installation Information in the manner specified by section 6 of the +GNU GPL for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the Library side by +side in a single library together with other library facilities that are not +Applications and are not covered by this License, and convey such a combined +library under terms of your choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities, conveyed under the terms +of this License. + + b) Give prominent notice with the combined library that part of it is a work +based on the Library, and explaining where to find the accompanying uncombined +form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions of the +GNU Lesser General Public License from time to time. Such new versions will be +similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + + Each version is given a distinguishing version number. If the Library as you +received it specifies that a certain numbered version of the GNU Lesser General +Public License "or any later version" applies to it, you have the option of +following the terms and conditions either of that published version or of any +later version published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser General Public +License, you may choose any version of the GNU Lesser General Public License +ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide whether +future versions of the GNU Lesser General Public License shall apply, that +proxy's public statement of acceptance of any version is permanent authorization +for you to choose that version for the Library. diff --git a/src/adi/hdl/Makefile b/src/adi/hdl/Makefile new file mode 100644 index 00000000..4d2d0434 --- /dev/null +++ b/src/adi/hdl/Makefile @@ -0,0 +1,50 @@ +#################################################################################### +#################################################################################### +## Copyright 2011(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### +#################################################################################### + +include quiet.mk + +help: + @echo "" + @echo "Please specify a target." + @echo "" + @echo "To make all projects:" + @echo " make all" + @echo "" + @echo "To build a specific project:" + @echo " make proj.board" + @echo "e.g.," + @echo " make adv7511.zed" + + +PROJECTS := $(filter-out $(NO_PROJ), $(notdir $(wildcard projects/*))) +SUBPROJECTS := $(foreach projname,$(PROJECTS), \ + $(foreach archname,$(notdir $(subst /Makefile,,$(wildcard projects/$(projname)/*/Makefile))), \ + $(projname).$(archname))) + +.PHONY: lib all clean clean-all $(SUBPROJECTS) + +$(SUBPROJECTS): + $(MAKE) -C projects/$(subst .,/,$@) + +lib: + $(MAKE) -C library/ all + + +all: + $(MAKE) -C projects/ all + + +clean: + $(MAKE) -C projects/ clean + + +clean-all:clean + $(MAKE) -C projects/ clean + $(MAKE) -C library/ clean + +#################################################################################### +#################################################################################### diff --git a/src/adi/hdl/README.md b/src/adi/hdl/README.md new file mode 100644 index 00000000..1e024f67 --- /dev/null +++ b/src/adi/hdl/README.md @@ -0,0 +1,72 @@ + +# HDL Reference Designs + +[Analog Devices Inc.](http://www.analog.com/en/index.html) HDL libraries and projects. + +## Getting started + +This repository supports reference designs for different [Analog Devices boards](../master/projects) based on [Intel and Xilinx FPGA development boards](../master/projects/common) or standalone. + +### Prerequisites + + * [Vivado Design Suite](https://www.xilinx.com/support/download.html) + +**or** + + * [Quartus Prime Design Suite](https://www.altera.com/downloads/download-center.html) + +Please make sure that you have the [required](https://github.com/analogdevicesinc/hdl/releases) tool version. + +### How to build a project + +For building a projects, you have to use the [GNU Make tool](https://www.gnu.org/software/make/). If you're a +Windows user please checkout [this page](https://wiki.analog.com/resources/fpga/docs/build#windows_environment_setup), to see how you can install this tool. + +To build a project, checkout the [latest release](https://github.com/analogdevicesinc/hdl/releases), after that just **cd** to the +project that you want to build and run make: +``` + [~]cd projects/fmcomms2/zc706 + [~]make +``` + +A more comprehensive build guide can be found under the following link: + + +## Software + +In general all the projects have no-OS (baremetal) and a Linux support. See [no-OS](https://github.com/analogdevicesinc/no-OS) or [Linux](https://github.com/analogdevicesinc/Linux) for +more information. + +## Which branch should I use? + + * If you want to use the most stable code base, always use the [latest release branch](https://github.com/analogdevicesinc/hdl/releases). + + * If you want to use the greatest and latest, check out the master branch. + +## License + +In this HDL repository, there are many different and unique modules, consisting +of various HDL (Verilog or VHDL) components. The individual modules are +developed independently, and may be accompanied by separate and unique license +terms. + +The user should read each of these license terms, and understand the +freedoms and responsibilities that he or she has by using this source/core. + +See [LICENSE](../master/LICENSE) for more details. The separate license files +cab be found here: + + * [LICENSE_ADIBSD](../master/LICENSE_ADIBSD) + + * [LICENSE_GPL2](../master/LICENSE_GPL2) + + * [LICENSE_LGPL](../master/LICENSE_LGPL) + +## Comprehensive user guide + +See [HDL User Guide](https://wiki.analog.com/resources/fpga/docs/hdl) for a more detailed guide. + +## Support + +Feel free to ask any question at [EngineerZone](https://ez.analog.com/community/fpga). + diff --git a/src/adi/hdl/library/Makefile b/src/adi/hdl/library/Makefile new file mode 100644 index 00000000..08b80ff6 --- /dev/null +++ b/src/adi/hdl/library/Makefile @@ -0,0 +1,227 @@ +#################################################################################### +#################################################################################### +## Copyright 2011(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### +#################################################################################### + +include ../quiet.mk + +.PHONY: all lib clean clean-all +all: lib + + +clean: + $(MAKE) -C altera/adi_jesd204 clean + $(MAKE) -C altera/avl_adxcfg clean + $(MAKE) -C altera/avl_adxcvr clean + $(MAKE) -C altera/avl_adxcvr_octet_swap clean + $(MAKE) -C altera/avl_adxphy clean + $(MAKE) -C altera/avl_dacfifo clean + $(MAKE) -C altera/axi_adxcvr clean + $(MAKE) -C altera/common/alt_ifconv clean + $(MAKE) -C altera/common/alt_mem_asym clean + $(MAKE) -C altera/common/alt_mul clean + $(MAKE) -C altera/common/alt_serdes clean + $(MAKE) -C altera/jesd204_phy clean + $(MAKE) -C axi_ad5766 clean + $(MAKE) -C axi_ad6676 clean + $(MAKE) -C axi_ad7616 clean + $(MAKE) -C axi_ad9122 clean + $(MAKE) -C axi_ad9144 clean + $(MAKE) -C axi_ad9152 clean + $(MAKE) -C axi_ad9162 clean + $(MAKE) -C axi_ad9250 clean + $(MAKE) -C axi_ad9265 clean + $(MAKE) -C axi_ad9361 clean + $(MAKE) -C axi_ad9371 clean + $(MAKE) -C axi_ad9434 clean + $(MAKE) -C axi_ad9467 clean + $(MAKE) -C axi_ad9625 clean + $(MAKE) -C axi_ad9671 clean + $(MAKE) -C axi_ad9680 clean + $(MAKE) -C axi_ad9684 clean + $(MAKE) -C axi_ad9739a clean + $(MAKE) -C axi_ad9963 clean + $(MAKE) -C axi_adc_decimate clean + $(MAKE) -C axi_adc_trigger clean + $(MAKE) -C axi_adrv9009 clean + $(MAKE) -C axi_clkgen clean + $(MAKE) -C axi_dac_interpolate clean + $(MAKE) -C axi_dmac clean + $(MAKE) -C axi_fmcadc5_sync clean + $(MAKE) -C axi_generic_adc clean + $(MAKE) -C axi_gpreg clean + $(MAKE) -C axi_hdmi_rx clean + $(MAKE) -C axi_hdmi_tx clean + $(MAKE) -C axi_i2s_adi clean + $(MAKE) -C axi_intr_monitor clean + $(MAKE) -C axi_logic_analyzer clean + $(MAKE) -C axi_mc_controller clean + $(MAKE) -C axi_mc_current_monitor clean + $(MAKE) -C axi_mc_speed clean + $(MAKE) -C axi_rd_wr_combiner clean + $(MAKE) -C axi_spdif_rx clean + $(MAKE) -C axi_spdif_tx clean + $(MAKE) -C axi_usb_fx3 clean + $(MAKE) -C cn0363/cn0363_dma_sequencer clean + $(MAKE) -C cn0363/cn0363_phase_data_sync clean + $(MAKE) -C cordic_demod clean + $(MAKE) -C jesd204/ad_ip_jesd204_tpl_adc clean + $(MAKE) -C jesd204/ad_ip_jesd204_tpl_dac clean + $(MAKE) -C jesd204/axi_jesd204_common clean + $(MAKE) -C jesd204/axi_jesd204_rx clean + $(MAKE) -C jesd204/axi_jesd204_tx clean + $(MAKE) -C jesd204/jesd204_common clean + $(MAKE) -C jesd204/jesd204_rx clean + $(MAKE) -C jesd204/jesd204_rx_static_config clean + $(MAKE) -C jesd204/jesd204_soft_pcs_rx clean + $(MAKE) -C jesd204/jesd204_soft_pcs_tx clean + $(MAKE) -C jesd204/jesd204_tx clean + $(MAKE) -C jesd204/jesd204_tx_static_config clean + $(MAKE) -C spi_engine/axi_spi_engine clean + $(MAKE) -C spi_engine/spi_engine_execution clean + $(MAKE) -C spi_engine/spi_engine_interconnect clean + $(MAKE) -C spi_engine/spi_engine_offload clean + $(MAKE) -C util_adcfifo clean + $(MAKE) -C util_axis_fifo clean + $(MAKE) -C util_axis_resize clean + $(MAKE) -C util_axis_upscale clean + $(MAKE) -C util_bsplit clean + $(MAKE) -C util_cdc clean + $(MAKE) -C util_cic clean + $(MAKE) -C util_clkdiv clean + $(MAKE) -C util_cpack clean + $(MAKE) -C util_dacfifo clean + $(MAKE) -C util_delay clean + $(MAKE) -C util_extract clean + $(MAKE) -C util_fir_dec clean + $(MAKE) -C util_fir_int clean + $(MAKE) -C util_gmii_to_rgmii clean + $(MAKE) -C util_i2c_mixer clean + $(MAKE) -C util_mfifo clean + $(MAKE) -C util_pulse_gen clean + $(MAKE) -C util_rfifo clean + $(MAKE) -C util_sigma_delta_spi clean + $(MAKE) -C util_tdd_sync clean + $(MAKE) -C util_upack clean + $(MAKE) -C util_var_fifo clean + $(MAKE) -C util_wfifo clean + $(MAKE) -C xilinx/axi_adcfifo clean + $(MAKE) -C xilinx/axi_adxcvr clean + $(MAKE) -C xilinx/axi_dacfifo clean + $(MAKE) -C xilinx/axi_xcvrlb clean + $(MAKE) -C xilinx/util_adxcvr clean + + $(MAKE) -C interfaces clean + + +clean-all:clean + + +lib: + $(MAKE) -C altera/adi_jesd204 + $(MAKE) -C altera/avl_adxcfg + $(MAKE) -C altera/avl_adxcvr + $(MAKE) -C altera/avl_adxcvr_octet_swap + $(MAKE) -C altera/avl_adxphy + $(MAKE) -C altera/avl_dacfifo + $(MAKE) -C altera/axi_adxcvr + $(MAKE) -C altera/common/alt_ifconv + $(MAKE) -C altera/common/alt_mem_asym + $(MAKE) -C altera/common/alt_mul + $(MAKE) -C altera/common/alt_serdes + $(MAKE) -C altera/jesd204_phy + $(MAKE) -C axi_ad5766 + $(MAKE) -C axi_ad6676 + $(MAKE) -C axi_ad7616 + $(MAKE) -C axi_ad9122 + $(MAKE) -C axi_ad9144 + $(MAKE) -C axi_ad9152 + $(MAKE) -C axi_ad9162 + $(MAKE) -C axi_ad9250 + $(MAKE) -C axi_ad9265 + $(MAKE) -C axi_ad9361 + $(MAKE) -C axi_ad9371 + $(MAKE) -C axi_ad9434 + $(MAKE) -C axi_ad9467 + $(MAKE) -C axi_ad9625 + $(MAKE) -C axi_ad9671 + $(MAKE) -C axi_ad9680 + $(MAKE) -C axi_ad9684 + $(MAKE) -C axi_ad9739a + $(MAKE) -C axi_ad9963 + $(MAKE) -C axi_adc_decimate + $(MAKE) -C axi_adc_trigger + $(MAKE) -C axi_adrv9009 + $(MAKE) -C axi_clkgen + $(MAKE) -C axi_dac_interpolate + $(MAKE) -C axi_dmac + $(MAKE) -C axi_fmcadc5_sync + $(MAKE) -C axi_generic_adc + $(MAKE) -C axi_gpreg + $(MAKE) -C axi_hdmi_rx + $(MAKE) -C axi_hdmi_tx + $(MAKE) -C axi_i2s_adi + $(MAKE) -C axi_intr_monitor + $(MAKE) -C axi_logic_analyzer + $(MAKE) -C axi_mc_controller + $(MAKE) -C axi_mc_current_monitor + $(MAKE) -C axi_mc_speed + $(MAKE) -C axi_rd_wr_combiner + $(MAKE) -C axi_spdif_rx + $(MAKE) -C axi_spdif_tx + $(MAKE) -C axi_usb_fx3 + $(MAKE) -C cn0363/cn0363_dma_sequencer + $(MAKE) -C cn0363/cn0363_phase_data_sync + $(MAKE) -C cordic_demod + $(MAKE) -C jesd204/ad_ip_jesd204_tpl_adc + $(MAKE) -C jesd204/ad_ip_jesd204_tpl_dac + $(MAKE) -C jesd204/axi_jesd204_common + $(MAKE) -C jesd204/axi_jesd204_rx + $(MAKE) -C jesd204/axi_jesd204_tx + $(MAKE) -C jesd204/jesd204_common + $(MAKE) -C jesd204/jesd204_rx + $(MAKE) -C jesd204/jesd204_rx_static_config + $(MAKE) -C jesd204/jesd204_soft_pcs_rx + $(MAKE) -C jesd204/jesd204_soft_pcs_tx + $(MAKE) -C jesd204/jesd204_tx + $(MAKE) -C jesd204/jesd204_tx_static_config + $(MAKE) -C spi_engine/axi_spi_engine + $(MAKE) -C spi_engine/spi_engine_execution + $(MAKE) -C spi_engine/spi_engine_interconnect + $(MAKE) -C spi_engine/spi_engine_offload + $(MAKE) -C util_adcfifo + $(MAKE) -C util_axis_fifo + $(MAKE) -C util_axis_resize + $(MAKE) -C util_axis_upscale + $(MAKE) -C util_bsplit + $(MAKE) -C util_cdc + $(MAKE) -C util_cic + $(MAKE) -C util_clkdiv + $(MAKE) -C util_cpack + $(MAKE) -C util_dacfifo + $(MAKE) -C util_delay + $(MAKE) -C util_extract + $(MAKE) -C util_fir_dec + $(MAKE) -C util_fir_int + $(MAKE) -C util_gmii_to_rgmii + $(MAKE) -C util_i2c_mixer + $(MAKE) -C util_mfifo + $(MAKE) -C util_pulse_gen + $(MAKE) -C util_rfifo + $(MAKE) -C util_sigma_delta_spi + $(MAKE) -C util_tdd_sync + $(MAKE) -C util_upack + $(MAKE) -C util_var_fifo + $(MAKE) -C util_wfifo + $(MAKE) -C xilinx/axi_adcfifo + $(MAKE) -C xilinx/axi_adxcvr + $(MAKE) -C xilinx/axi_dacfifo + $(MAKE) -C xilinx/axi_xcvrlb + $(MAKE) -C xilinx/util_adxcvr + + $(MAKE) -C interfaces + +#################################################################################### +#################################################################################### diff --git a/src/adi/hdl/library/altera/common/ad_dcfilter.v b/src/adi/hdl/library/altera/common/ad_dcfilter.v new file mode 100644 index 00000000..2cd19c3e --- /dev/null +++ b/src/adi/hdl/library/altera/common/ad_dcfilter.v @@ -0,0 +1,85 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// dc filter- y(n) = c*x(n) + (1-c)*y(n-1) +// NOT IMPLEMENTED + +`timescale 1ps/1ps + +module ad_dcfilter #( + + // data path disable + + parameter DISABLE = 0) ( + + // data interface + + input clk, + input valid, + input [15:0] data, + output reg valid_out, + output reg [15:0] data_out, + + // control interface + + input dcfilt_enb, + input [15:0] dcfilt_coeff, + input [15:0] dcfilt_offset); + + // internal registers + + reg valid_d = 'd0; + reg [15:0] data_d = 'd0; + reg valid_2d = 'd0; + reg [15:0] data_2d = 'd0; + + // internal signals + + wire [47:0] dc_offset_s; + + always @(posedge clk) begin + valid_d <= valid; + if (valid == 1'b1) begin + data_d <= data + dcfilt_offset; + end + valid_2d <= valid_d; + data_2d <= data_d; + valid_out <= valid_2d; + data_out <= data_2d; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/altera/common/ad_mul.v b/src/adi/hdl/library/altera/common/ad_mul.v new file mode 100644 index 00000000..eaaef8b7 --- /dev/null +++ b/src/adi/hdl/library/altera/common/ad_mul.v @@ -0,0 +1,90 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ps/1ps + +module ad_mul #( + + parameter A_DATA_WIDTH = 17, + parameter B_DATA_WIDTH = 17, + parameter DELAY_DATA_WIDTH = 16) ( + + // data_p = data_a * data_b; + + input clk, + input [ A_DATA_WIDTH-1:0] data_a, + input [ B_DATA_WIDTH-1:0] data_b, + output [A_DATA_WIDTH + B_DATA_WIDTH-1:0] data_p, + + // delay interface + + input [(DELAY_DATA_WIDTH-1):0] ddata_in, + output reg [(DELAY_DATA_WIDTH-1):0] ddata_out); + + + // internal registers + + reg [(DELAY_DATA_WIDTH-1):0] p1_ddata = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] p2_ddata = 'd0; + + // a/b reg, m-reg, p-reg delay match + + always @(posedge clk) begin + p1_ddata <= ddata_in; + p2_ddata <= p1_ddata; + ddata_out <= p2_ddata; + end + + lpm_mult #( + .lpm_type ("lpm_mult"), + .lpm_widtha (A_DATA_WIDTH), + .lpm_widthb (B_DATA_WIDTH), + .lpm_widthp (A_DATA_WIDTH + B_DATA_WIDTH), + .lpm_representation ("SIGNED"), + .lpm_pipeline (3)) + i_lpm_mult ( + .clken (1'b1), + .aclr (1'b0), + .sclr (1'b0), + .sum (1'b0), + .clock (clk), + .dataa (data_a), + .datab (data_b), + .result (data_p)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/altera/common/alt_ifconv/Makefile b/src/adi/hdl/library/altera/common/alt_ifconv/Makefile new file mode 100644 index 00000000..2fa8c247 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_ifconv/Makefile @@ -0,0 +1,11 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := alt_ifconv + +ALTERA_DEPS += alt_ifconv.v +ALTERA_DEPS += alt_ifconv_hw.tcl + +include ../../../scripts/library.mk diff --git a/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv.v b/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv.v new file mode 100644 index 00000000..3bf502ab --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv.v @@ -0,0 +1,60 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module alt_ifconv #( + + // parameters + + parameter WIDTH = 1, + parameter INTERFACE_NAME_IN = "input-interface-name", + parameter INTERFACE_NAME_OUT = "output-interface-name", + parameter SIGNAL_NAME_IN = "input-signal-name", + parameter SIGNAL_NAME_OUT = "output-signal-name") ( + + // bad tools - ugly stuff + + input [(WIDTH-1):0] din, + output [(WIDTH-1):0] dout); + + // avoiding qsys signal conflicts + + assign dout = din; + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv_hw.tcl b/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv_hw.tcl new file mode 100644 index 00000000..4e16e4d3 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_ifconv/alt_ifconv_hw.tcl @@ -0,0 +1,34 @@ + +package require qsys + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_alt.tcl + +ad_ip_create alt_ifconv {Altera Interface Translator} alt_ifconv_elab +ad_ip_files alt_ifconv { \ + $ad_hdl_dir/library/altera/common/alt_ifconv/alt_ifconv.v \ +} + +# parameters + +ad_ip_parameter DEVICE_FAMILY STRING {Arria 10} +ad_ip_parameter WIDTH INTEGER 1 +ad_ip_parameter INTERFACE_NAME_IN STRING {input-interface-name} +ad_ip_parameter INTERFACE_NAME_OUT STRING {output-interface-name} +ad_ip_parameter SIGNAL_NAME_IN STRING {input-signal-name} +ad_ip_parameter SIGNAL_NAME_OUT STRING {output-signal-name} + +proc alt_ifconv_elab {} { + + set m_width [get_parameter_value "WIDTH"] + set m_if_name_in [get_parameter_value "INTERFACE_NAME_IN"] + set m_if_name_out [get_parameter_value "INTERFACE_NAME_OUT"] + set m_sig_name_in [get_parameter_value "SIGNAL_NAME_IN"] + set m_sig_name_out [get_parameter_value "SIGNAL_NAME_OUT"] + + add_interface $m_if_name_in conduit end + add_interface_port $m_if_name_in din $m_sig_name_in input $m_width + add_interface $m_if_name_out conduit end + add_interface_port $m_if_name_out dout $m_sig_name_out output $m_width +} + diff --git a/src/adi/hdl/library/altera/common/alt_mem_asym/Makefile b/src/adi/hdl/library/altera/common/alt_mem_asym/Makefile new file mode 100644 index 00000000..126d3ada --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_mem_asym/Makefile @@ -0,0 +1,10 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := alt_mem_asym + +ALTERA_DEPS += alt_mem_asym_hw.tcl + +include ../../../scripts/library.mk diff --git a/src/adi/hdl/library/altera/common/alt_mem_asym/alt_mem_asym_hw.tcl b/src/adi/hdl/library/altera/common/alt_mem_asym/alt_mem_asym_hw.tcl new file mode 100644 index 00000000..77fe3cb7 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_mem_asym/alt_mem_asym_hw.tcl @@ -0,0 +1,49 @@ + +package require qsys + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_alt.tcl + +ad_ip_create alt_mem_asym {Altera Asymmetric Memory} +set_module_property COMPOSITION_CALLBACK p_alt_mem_asym + +# parameters + +ad_ip_parameter DEVICE_FAMILY STRING {Arria 10} +ad_ip_parameter A_ADDRESS_WIDTH INTEGER 8 +ad_ip_parameter A_DATA_WIDTH INTEGER 512 +ad_ip_parameter B_ADDRESS_WIDTH INTEGER 8 +ad_ip_parameter B_DATA_WIDTH INTEGER 64 + +# compose + +proc p_alt_mem_asym {} { + + set m_addr_width_a [get_parameter_value "A_ADDRESS_WIDTH"] + set m_data_width_a [get_parameter_value "A_DATA_WIDTH"] + set m_addr_width_b [get_parameter_value "B_ADDRESS_WIDTH"] + set m_data_width_b [get_parameter_value "B_DATA_WIDTH"] + + set m_size [expr ((2**$m_addr_width_a)*$m_data_width_a)] + if {$m_addr_width_a == 0} { + set m_size [expr ((2**$m_addr_width_b)*$m_data_width_b)] + } + + add_instance alt_mem ram_2port + set_instance_parameter_value alt_mem {GUI_MODE} 0 + set_instance_parameter_value alt_mem {GUI_MEM_IN_BITS} 1 + set_instance_parameter_value alt_mem {GUI_MEMSIZE_BITS} $m_size + set_instance_parameter_value alt_mem {GUI_VAR_WIDTH} 1 + set_instance_parameter_value alt_mem {GUI_QA_WIDTH} $m_data_width_a + set_instance_parameter_value alt_mem {GUI_DATAA_WIDTH} $m_data_width_a + set_instance_parameter_value alt_mem {GUI_QB_WIDTH} $m_data_width_b + set_instance_parameter_value alt_mem {GUI_READ_OUTPUT_QB} {false} + set_instance_parameter_value alt_mem {GUI_RAM_BLOCK_TYPE} {M20K} + set_instance_parameter_value alt_mem {GUI_CLOCK_TYPE} 1 + + add_interface mem_i conduit end + add_interface mem_o conduit end + set_interface_property mem_i EXPORT_OF alt_mem.ram_input + set_interface_property mem_o EXPORT_OF alt_mem.ram_output +} + diff --git a/src/adi/hdl/library/altera/common/alt_mul/Makefile b/src/adi/hdl/library/altera/common/alt_mul/Makefile new file mode 100644 index 00000000..c0152d5e --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_mul/Makefile @@ -0,0 +1,10 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := alt_mul + +ALTERA_DEPS += alt_mul_hw.tcl + +include ../../../scripts/library.mk diff --git a/src/adi/hdl/library/altera/common/alt_mul/alt_mul_hw.tcl b/src/adi/hdl/library/altera/common/alt_mul/alt_mul_hw.tcl new file mode 100644 index 00000000..11428e32 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_mul/alt_mul_hw.tcl @@ -0,0 +1,35 @@ + +package require qsys + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_alt.tcl + +ad_ip_create alt_mul {Altera LPM Multiplier} +set_module_property COMPOSITION_CALLBACK p_alt_mul + +# parameters + +ad_ip_parameter DEVICE_FAMILY STRING {Arria 10} + +# compose + +proc p_alt_mul {} { + + add_instance alt_mul lpm_mult + set_instance_parameter_value alt_mul {GUI_USE_MULT} {1} + set_instance_parameter_value alt_mul {GUI_WIDTH_A} {17} + set_instance_parameter_value alt_mul {GUI_WIDTH_B} {17} + set_instance_parameter_value alt_mul {GUI_AUTO_SIZE_RESULT} {0} + set_instance_parameter_value alt_mul {GUI_WIDTH_P} {34} + set_instance_parameter_value alt_mul {GUI_B_IS_CONSTANT} {0} + set_instance_parameter_value alt_mul {GUI_SIGNED_MULT} {1} + set_instance_parameter_value alt_mul {GUI_PIPELINE} {1} + set_instance_parameter_value alt_mul {GUI_LATENCY} {3} + set_instance_parameter_value alt_mul {GUI_OPTIMIZE} {1} + + add_interface mult_i conduit end + add_interface mult_o conduit end + set_interface_property mult_i EXPORT_OF alt_mul.mult_input + set_interface_property mult_o EXPORT_OF alt_mul.mult_output +} + diff --git a/src/adi/hdl/library/altera/common/alt_serdes/Makefile b/src/adi/hdl/library/altera/common/alt_serdes/Makefile new file mode 100644 index 00000000..4ba4f424 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_serdes/Makefile @@ -0,0 +1,10 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := alt_serdes + +ALTERA_DEPS += alt_serdes_hw.tcl + +include ../../../scripts/library.mk diff --git a/src/adi/hdl/library/altera/common/alt_serdes/alt_serdes_hw.tcl b/src/adi/hdl/library/altera/common/alt_serdes/alt_serdes_hw.tcl new file mode 100644 index 00000000..bd2e3106 --- /dev/null +++ b/src/adi/hdl/library/altera/common/alt_serdes/alt_serdes_hw.tcl @@ -0,0 +1,132 @@ + +package require qsys + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_alt.tcl + +ad_ip_create alt_serdes {Altera SERDES} +set_module_property COMPOSITION_CALLBACK p_alt_serdes + +# parameters + +ad_ip_parameter DEVICE_FAMILY STRING {Arria 10} +ad_ip_parameter MODE STRING "CLK" false +ad_ip_parameter DDR_OR_SDR_N INTEGER 1 false +ad_ip_parameter SERDES_FACTOR INTEGER 8 false +ad_ip_parameter CLKIN_FREQUENCY FLOAT 500.0 false + +set_parameter_property MODE ALLOWED_RANGES {"CLK" "IN" "OUT"} +set_parameter_property DDR_OR_SDR_N ALLOWED_RANGES {0 1} +set_parameter_property SERDES_FACTOR ALLOWED_RANGES {4 8} +set_parameter_property CLKIN_FREQUENCY DISPLAY_UNITS "MHz" + +proc p_alt_serdes {} { + + set m_mode [get_parameter_value "MODE"] + set m_ddr_or_sdr_n [get_parameter_value "DDR_OR_SDR_N"] + set m_serdes_factor [get_parameter_value "SERDES_FACTOR"] + set m_clkin_frequency [get_parameter_value "CLKIN_FREQUENCY"] + + set m_hs_data_rate [expr ($m_clkin_frequency * ($m_ddr_or_sdr_n + 1))] + set m_ls_data_rate [expr ($m_hs_data_rate/$m_serdes_factor)] + + set m_ls_phase 22.5 + set m_ld_phase 315.0 + set m_ld_duty_cycle 12.5 + + if {$m_serdes_factor == 4} { + set m_ls_phase 45 + set m_ld_phase 270.0 + set m_ld_duty_cycle 25.0 + } + + ## arria 10 only + + if {$m_mode == "CLK"} { + add_instance alt_serdes_pll altera_iopll + set_instance_parameter_value alt_serdes_pll {gui_reference_clock_frequency} $m_clkin_frequency + set_instance_parameter_value alt_serdes_pll {gui_use_locked} {1} + set_instance_parameter_value alt_serdes_pll {gui_operation_mode} {lvds} + set_instance_parameter_value alt_serdes_pll {gui_number_of_clocks} {3} + set_instance_parameter_value alt_serdes_pll {gui_en_lvds_ports} {Enable LVDS_CLK/LOADEN 0} + set_instance_parameter_value alt_serdes_pll {gui_en_phout_ports} {true} + set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency0} $m_hs_data_rate + set_instance_parameter_value alt_serdes_pll {gui_ps_units0} {degrees} + set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg0} {180.0} + set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency1} $m_ls_data_rate + set_instance_parameter_value alt_serdes_pll {gui_ps_units1} {degrees} + set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg1} $m_ld_phase + set_instance_parameter_value alt_serdes_pll {gui_duty_cycle1} $m_ld_duty_cycle + set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency2} $m_ls_data_rate + set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg2} $m_ls_phase + set_instance_parameter_value alt_serdes_pll {gui_ps_units2} {degrees} + add_interface rst reset sink + set_interface_property rst EXPORT_OF alt_serdes_pll.reset + add_interface ref_clk clock sink + set_interface_property ref_clk EXPORT_OF alt_serdes_pll.refclk + add_interface locked conduit end + set_interface_property locked EXPORT_OF alt_serdes_pll.locked + add_interface hs_phase conduit end + set_interface_property hs_phase EXPORT_OF alt_serdes_pll.phout + add_interface hs_clk conduit end + set_interface_property hs_clk EXPORT_OF alt_serdes_pll.lvds_clk + add_interface loaden conduit end + set_interface_property loaden EXPORT_OF alt_serdes_pll.loaden + add_interface ls_clk clock source + set_interface_property ls_clk EXPORT_OF alt_serdes_pll.outclk2 + return + } + + if {$m_mode == "IN"} { + add_instance alt_serdes_in altera_lvds + set_instance_parameter_value alt_serdes_in {MODE} {RX_DPA-FIFO} + set_instance_parameter_value alt_serdes_in {NUM_CHANNELS} {1} + set_instance_parameter_value alt_serdes_in {DATA_RATE} $m_hs_data_rate + set_instance_parameter_value alt_serdes_in {J_FACTOR} $m_serdes_factor + set_instance_parameter_value alt_serdes_in {USE_EXTERNAL_PLL} {true} + set_instance_parameter_value alt_serdes_in {INCLOCK_FREQUENCY} $m_clkin_frequency + set_instance_parameter_value alt_serdes_in {PLL_USE_RESET} {false} + add_interface data_in conduit end + set_interface_property data_in EXPORT_OF alt_serdes_in.rx_in + add_interface clk conduit end + set_interface_property clk EXPORT_OF alt_serdes_in.ext_fclk + add_interface loaden conduit end + set_interface_property loaden EXPORT_OF alt_serdes_in.ext_loaden + add_interface div_clk conduit end + set_interface_property div_clk EXPORT_OF alt_serdes_in.ext_coreclock + add_interface hs_phase conduit end + set_interface_property hs_phase EXPORT_OF alt_serdes_in.ext_vcoph + add_interface locked conduit end + set_interface_property locked EXPORT_OF alt_serdes_in.ext_pll_locked + add_interface data_s conduit end + set_interface_property data_s EXPORT_OF alt_serdes_in.rx_out + add_interface delay_locked conduit end + set_interface_property delay_locked EXPORT_OF alt_serdes_in.rx_dpa_locked + return + } + + if {$m_mode == "OUT"} { + add_instance alt_serdes_out altera_lvds + set_instance_parameter_value alt_serdes_out {MODE} {TX} + set_instance_parameter_value alt_serdes_out {NUM_CHANNELS} {1} + set_instance_parameter_value alt_serdes_out {DATA_RATE} $m_hs_data_rate + set_instance_parameter_value alt_serdes_out {J_FACTOR} $m_serdes_factor + set_instance_parameter_value alt_serdes_out {TX_EXPORT_CORECLOCK} {false} + set_instance_parameter_value alt_serdes_out {TX_USE_OUTCLOCK} {false} + set_instance_parameter_value alt_serdes_out {USE_EXTERNAL_PLL} {true} + set_instance_parameter_value alt_serdes_out {INCLOCK_FREQUENCY} $m_clkin_frequency + set_instance_parameter_value alt_serdes_out {PLL_USE_RESET} {false} + add_interface data_out conduit end + set_interface_property data_out EXPORT_OF alt_serdes_out.tx_out + add_interface clk conduit end + set_interface_property clk EXPORT_OF alt_serdes_out.ext_fclk + add_interface loaden conduit end + set_interface_property loaden EXPORT_OF alt_serdes_out.ext_loaden + add_interface div_clk conduit end + set_interface_property div_clk EXPORT_OF alt_serdes_out.ext_coreclock + add_interface data_s conduit end + set_interface_property data_s EXPORT_OF alt_serdes_out.tx_in + return + } +} + diff --git a/src/adi/hdl/library/altera/common/up_clock_mon_constr.sdc b/src/adi/hdl/library/altera/common/up_clock_mon_constr.sdc new file mode 100644 index 00000000..b01a9f28 --- /dev/null +++ b/src/adi/hdl/library/altera/common/up_clock_mon_constr.sdc @@ -0,0 +1,4 @@ + +set_false_path -from [get_registers *up_clock_mon:i_clock_mon|d_count_run_m3*] -to [get_registers *up_clock_mon:i_clock_mon|up_count_running_m1*] +set_false_path -from [get_registers *up_clock_mon:i_clock_mon|up_count_run*] -to [get_registers *up_clock_mon:i_clock_mon|d_count_run_m1*] +set_false_path -from [get_registers *up_clock_mon:i_clock_mon|d_count*] -to [get_registers *up_clock_mon:i_clock_mon|up_d_count*] diff --git a/src/adi/hdl/library/altera/common/up_rst_constr.sdc b/src/adi/hdl/library/altera/common/up_rst_constr.sdc new file mode 100644 index 00000000..95fe2ad9 --- /dev/null +++ b/src/adi/hdl/library/altera/common/up_rst_constr.sdc @@ -0,0 +1,4 @@ + +set_false_path -to [get_pins -hierarchical -nocase rst_async_d*|CLRN] +set_false_path -to [get_pins -hierarchical -nocase rst_sync|CLRN] + diff --git a/src/adi/hdl/library/altera/common/up_xfer_cntrl_constr.sdc b/src/adi/hdl/library/altera/common/up_xfer_cntrl_constr.sdc new file mode 100644 index 00000000..0b4c0ba7 --- /dev/null +++ b/src/adi/hdl/library/altera/common/up_xfer_cntrl_constr.sdc @@ -0,0 +1,4 @@ + +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_cntrl|d_xfer_toggle*] -to [get_registers *up_xfer_cntrl:i_xfer_cntrl|up_xfer_state_m1*] +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_cntrl|up_xfer_toggle*] -to [get_registers *up_xfer_cntrl:i_xfer_cntrl|d_xfer_toggle_m1*] +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_cntrl|up_xfer_data*] -to [get_registers *up_xfer_cntrl:i_xfer_cntrl|d_data_cntrl*] diff --git a/src/adi/hdl/library/altera/common/up_xfer_status_constr.sdc b/src/adi/hdl/library/altera/common/up_xfer_status_constr.sdc new file mode 100644 index 00000000..432525b0 --- /dev/null +++ b/src/adi/hdl/library/altera/common/up_xfer_status_constr.sdc @@ -0,0 +1,4 @@ + +set_false_path -from [get_registers *up_xfer_status:i_xfer_status|up_xfer_toggle*] -to [get_registers *up_xfer_status:i_xfer_status|d_xfer_state_m1*] +set_false_path -from [get_registers *up_xfer_status:i_xfer_status|d_xfer_toggle*] -to [get_registers *up_xfer_status:i_xfer_status|up_xfer_toggle_m1*] +set_false_path -from [get_registers *up_xfer_status:i_xfer_status|d_xfer_data*] -to [get_registers *up_xfer_status:i_xfer_status|up_data_status*] diff --git a/src/adi/hdl/library/axi_clkgen/Makefile b/src/adi/hdl/library/axi_clkgen/Makefile new file mode 100644 index 00000000..041c35f4 --- /dev/null +++ b/src/adi/hdl/library/axi_clkgen/Makefile @@ -0,0 +1,17 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_clkgen + +GENERIC_DEPS += ../common/ad_rst.v +GENERIC_DEPS += ../common/up_axi.v +GENERIC_DEPS += ../common/up_clkgen.v +GENERIC_DEPS += axi_clkgen.v + +XILINX_DEPS += ../xilinx/common/ad_mmcm_drp.v +XILINX_DEPS += axi_clkgen_ip.tcl +XILINX_DEPS += bd/bd.tcl + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/axi_clkgen/axi_clkgen.v b/src/adi/hdl/library/axi_clkgen/axi_clkgen.v new file mode 100644 index 00000000..582495e7 --- /dev/null +++ b/src/adi/hdl/library/axi_clkgen/axi_clkgen.v @@ -0,0 +1,215 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// software programmable clock generator (still needs a reference input!) + +`timescale 1ns/100ps + +module axi_clkgen #( + + parameter ID = 0, + parameter DEVICE_TYPE = 0, + parameter CLKSEL_EN = 0, + parameter real CLKIN_PERIOD = 5.000, + parameter real CLKIN2_PERIOD = 5.000, + parameter integer VCO_DIV = 11, + parameter real VCO_MUL = 49.000, + parameter real CLK0_DIV = 6.000, + parameter real CLK0_PHASE = 0.000, + parameter integer CLK1_DIV = 6, + parameter real CLK1_PHASE = 0.000) ( + + // clocks + + input clk, + input clk2, + output clk_0, + output clk_1, + + // axi interface + + input s_axi_aclk, + input s_axi_aresetn, + input s_axi_awvalid, + input [15:0] s_axi_awaddr, + output s_axi_awready, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [15:0] s_axi_araddr, + output s_axi_arready, + output s_axi_rvalid, + output [31:0] s_axi_rdata, + output [ 1:0] s_axi_rresp, + input s_axi_rready, + input [ 2:0] s_axi_awprot, + input [ 2:0] s_axi_arprot); + + + // reset and clocks + + wire mmcm_rst; + wire clk_sel_s; + wire up_clk_sel_s; + wire up_rstn; + wire up_clk; + + // internal signals + + wire up_drp_sel_s; + wire up_drp_wr_s; + wire [11:0] up_drp_addr_s; + wire [15:0] up_drp_wdata_s; + wire [15:0] up_drp_rdata_s; + wire up_drp_ready_s; + wire up_drp_locked_s; + wire up_wreq_s; + wire [13:0] up_waddr_s; + wire [31:0] up_wdata_s; + wire up_wack_s; + wire up_rreq_s; + wire [13:0] up_raddr_s; + wire [31:0] up_rdata_s; + wire up_rack_s; + + // signal name changes + + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + + // up bus interface + + up_axi i_up_axi ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_axi_awvalid (s_axi_awvalid), + .up_axi_awaddr (s_axi_awaddr), + .up_axi_awready (s_axi_awready), + .up_axi_wvalid (s_axi_wvalid), + .up_axi_wdata (s_axi_wdata), + .up_axi_wstrb (s_axi_wstrb), + .up_axi_wready (s_axi_wready), + .up_axi_bvalid (s_axi_bvalid), + .up_axi_bresp (s_axi_bresp), + .up_axi_bready (s_axi_bready), + .up_axi_arvalid (s_axi_arvalid), + .up_axi_araddr (s_axi_araddr), + .up_axi_arready (s_axi_arready), + .up_axi_rvalid (s_axi_rvalid), + .up_axi_rresp (s_axi_rresp), + .up_axi_rdata (s_axi_rdata), + .up_axi_rready (s_axi_rready), + .up_wreq (up_wreq_s), + .up_waddr (up_waddr_s), + .up_wdata (up_wdata_s), + .up_wack (up_wack_s), + .up_rreq (up_rreq_s), + .up_raddr (up_raddr_s), + .up_rdata (up_rdata_s), + .up_rack (up_rack_s)); + + // processor interface + + up_clkgen #( + .ID(ID) + ) i_up_clkgen ( + .mmcm_rst (mmcm_rst), + .clk_sel (up_clk_sel_s), + .up_drp_sel (up_drp_sel_s), + .up_drp_wr (up_drp_wr_s), + .up_drp_addr (up_drp_addr_s), + .up_drp_wdata (up_drp_wdata_s), + .up_drp_rdata (up_drp_rdata_s), + .up_drp_ready (up_drp_ready_s), + .up_drp_locked (up_drp_locked_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq_s), + .up_waddr (up_waddr_s), + .up_wdata (up_wdata_s), + .up_wack (up_wack_s), + .up_rreq (up_rreq_s), + .up_raddr (up_raddr_s), + .up_rdata (up_rdata_s), + .up_rack (up_rack_s)); + + // If CLKSEL_EN is not active, the clk0 port of the MMCM is used, this + // should be used when the MMCM has only one active clock source + + generate if (CLKSEL_EN == 1) begin + assign clk_sel_s = up_clk_sel_s; + end else begin + assign clk_sel_s = 1'b1; + end + endgenerate + + // mmcm instantiations + + ad_mmcm_drp #( + .MMCM_DEVICE_TYPE (DEVICE_TYPE), + .MMCM_CLKIN_PERIOD (CLKIN_PERIOD), + .MMCM_CLKIN2_PERIOD (CLKIN2_PERIOD), + .MMCM_VCO_DIV (VCO_DIV), + .MMCM_VCO_MUL (VCO_MUL), + .MMCM_CLK0_DIV (CLK0_DIV), + .MMCM_CLK0_PHASE (CLK0_PHASE), + .MMCM_CLK1_DIV (CLK1_DIV), + .MMCM_CLK1_PHASE (CLK1_PHASE)) + i_mmcm_drp ( + .clk (clk), + .clk2 (clk2), + .clk_sel(clk_sel_s), + .mmcm_rst (mmcm_rst), + .mmcm_clk_0 (clk_0), + .mmcm_clk_1 (clk_1), + .mmcm_clk_2 (), + .up_clk (up_clk), + .up_rstn (up_rstn), + .up_drp_sel (up_drp_sel_s), + .up_drp_wr (up_drp_wr_s), + .up_drp_addr (up_drp_addr_s), + .up_drp_wdata (up_drp_wdata_s), + .up_drp_rdata (up_drp_rdata_s), + .up_drp_ready (up_drp_ready_s), + .up_drp_locked (up_drp_locked_s)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/axi_clkgen/axi_clkgen_ip.tcl b/src/adi/hdl/library/axi_clkgen/axi_clkgen_ip.tcl new file mode 100644 index 00000000..f6ab698f --- /dev/null +++ b/src/adi/hdl/library/axi_clkgen/axi_clkgen_ip.tcl @@ -0,0 +1,52 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_clkgen +adi_ip_files axi_clkgen [list \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_mmcm_drp.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/common/up_clkgen.v" \ + "bd/bd.tcl" \ + "axi_clkgen.v" ] + +adi_ip_properties axi_clkgen +adi_ip_bd axi_clkgen "bd/bd.tcl" + +ipx::infer_bus_interface clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface clk2 xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface clk_0 xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface clk_1 xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] + +set cc [ipx::current_core] +set page0 [ipgui::get_pagespec -name "Page 0" -component $cc] + +set param [ipx::add_user_parameter ENABLE_CLKIN2 $cc] +set_property -dict {value_resolve_type user value_format bool value false} $param + +set param [ipgui::add_param -name {ENABLE_CLKIN2} -component $cc -parent $page0] +set_property -dict [list \ + display_name {Enable secondary clock input} \ + widget {checkBox} \ +] $param + +set param [ipx::add_user_parameter ENABLE_CLKOUT1 $cc] +set_property -dict {value_resolve_type user value_format bool value false} $param + +set param [ipgui::add_param -name {ENABLE_CLKOUT1} -component $cc -parent $page0] +set_property -dict [list \ + display_name {Enable secondary clock output} \ + widget {checkBox} \ +] $param + +set_property enablement_tcl_expr {$ENABLE_CLKIN2} [ipx::get_user_parameters CLKIN2_PERIOD -of_objects $cc] +set_property enablement_tcl_expr {$ENABLE_CLKOUT1} [ipx::get_user_parameters CLK1_DIV -of_objects $cc] +set_property enablement_tcl_expr {$ENABLE_CLKOUT1} [ipx::get_user_parameters CLK1_PHASE -of_objects $cc] + +adi_set_ports_dependency clk2 ENABLE_CLKIN2 0 +adi_set_ports_dependency clk_1 ENABLE_CLKOUT1 + +ipx::create_xgui_files $cc +ipx::save_core $cc diff --git a/src/adi/hdl/library/axi_clkgen/bd/bd.tcl b/src/adi/hdl/library/axi_clkgen/bd/bd.tcl new file mode 100644 index 00000000..4e92dab3 --- /dev/null +++ b/src/adi/hdl/library/axi_clkgen/bd/bd.tcl @@ -0,0 +1,75 @@ +proc init {cellpath otherInfo} { + set ip [get_bd_cells $cellpath] + + bd::mark_propagate_override $ip \ + "CLKIN_PERIOD CLKIN2_PERIOD" +} + +proc axi_clkgen_get_infer_period {ip param clk_name} { + set param_src [get_property "CONFIG.$param.VALUE_SRC" $ip] + if {[string equal $param_src "USER"]} { + return; + } + + set clk [get_bd_pins "$ip/$clk_name"] + set clk_freq [get_property CONFIG.FREQ_HZ $clk] + + if {$clk_freq != {}} { + set clk_period [expr 1000000000.0 / $clk_freq] + set_property "CONFIG.$param" [format "%.6f" $clk_period] $ip + } +} + +proc propagate {cellpath otherinfo} { + set ip [get_bd_cells $cellpath] + + set vco_mul [get_property CONFIG.VCO_MUL $ip] + set vco_div [get_property CONFIG.VCO_DIV $ip] + set clk0_div [get_property CONFIG.CLK0_DIV $ip] + set clk1_div [get_property CONFIG.CLK1_DIV $ip] + + if {$vco_mul == {} || $vco_mul < 1} { + set vco_mul 1 + } + if {$vco_div == {} || $vco_div < 1} { + set vco_div 1 + } + if {$clk0_div == {} || $clk0_div < 1} { + set clk0_div 1 + } + if {$clk1_div == {} || $clk0_div < 1} { + set clk1_div 1 + } + + set clk [get_bd_pins "$ip/clk"] + set clk_freq [get_property CONFIG.FREQ_HZ $clk] + if {[get_property "CONFIG.ENABLE_CLKIN2" $ip] == "true"} { + set clk2 [get_bd_pins "$ip/clk"] + set clk2_freq [get_property CONFIG.FREQ_HZ $clk2] + # Use the larger of the two + if {$clk_freq == {} || $clk2_freq > $clk_freq} { + set clk_freq $clk2_freq + } + } + + if {$clk_freq != {}} { + set clk0_out [get_bd_pins "$ip/clk_0"] + set clk0_out_freq [expr ($clk_freq + 0.0) * $vco_mul / ($vco_div * $clk0_div)] + set_property CONFIG.FREQ_HZ $clk0_out_freq $clk0_out + + if {[get_property "CONFIG.ENABLE_CLKOUT1" $ip] == "true"} { + set clk0_out [get_bd_pins "$ip/clk_1"] + set clk1_out_freq [expr ($clk_freq + 0.0) * $vco_mul / ($vco_div * $clk1_div)] + set_property CONFIG.FREQ_HZ $clk1_out_freq $clk1_out + } + } +} + +proc post_propagate {cellpath otherinfo} { + set ip [get_bd_cells $cellpath] + + axi_clkgen_get_infer_period $ip CLKIN_PERIOD clk + if {[get_property "CONFIG.ENABLE_CLKIN2" $ip] == "true"} { + axi_clkgen_get_infer_period $ip CLKIN2_PERIOD clk2 + } +} diff --git a/src/adi/hdl/library/axi_hdmi_tx/Makefile b/src/adi/hdl/library/axi_hdmi_tx/Makefile new file mode 100644 index 00000000..609b75bd --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/Makefile @@ -0,0 +1,41 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_hdmi_tx + +GENERIC_DEPS += ../common/ad_csc_1.v +GENERIC_DEPS += ../common/ad_csc_1_add.v +GENERIC_DEPS += ../common/ad_csc_1_mul.v +GENERIC_DEPS += ../common/ad_csc_RGB2CrYCb.v +GENERIC_DEPS += ../common/ad_mem.v +GENERIC_DEPS += ../common/ad_rst.v +GENERIC_DEPS += ../common/ad_ss_444to422.v +GENERIC_DEPS += ../common/up_axi.v +GENERIC_DEPS += ../common/up_clock_mon.v +GENERIC_DEPS += ../common/up_hdmi_tx.v +GENERIC_DEPS += ../common/up_xfer_cntrl.v +GENERIC_DEPS += ../common/up_xfer_status.v +GENERIC_DEPS += axi_hdmi_tx.v +GENERIC_DEPS += axi_hdmi_tx_core.v +GENERIC_DEPS += axi_hdmi_tx_es.v +GENERIC_DEPS += axi_hdmi_tx_vdma.v + +XILINX_DEPS += ../xilinx/common/ad_mul.v +XILINX_DEPS += ../xilinx/common/ad_rst_constr.xdc +XILINX_DEPS += ../xilinx/common/up_clock_mon_constr.xdc +XILINX_DEPS += ../xilinx/common/up_xfer_cntrl_constr.xdc +XILINX_DEPS += ../xilinx/common/up_xfer_status_constr.xdc +XILINX_DEPS += axi_hdmi_tx_constr.xdc +XILINX_DEPS += axi_hdmi_tx_ip.tcl + +ALTERA_DEPS += ../altera/common/ad_mul.v +ALTERA_DEPS += ../altera/common/up_clock_mon_constr.sdc +ALTERA_DEPS += ../altera/common/up_rst_constr.sdc +ALTERA_DEPS += ../altera/common/up_xfer_cntrl_constr.sdc +ALTERA_DEPS += ../altera/common/up_xfer_status_constr.sdc +ALTERA_DEPS += axi_hdmi_tx_constr.sdc +ALTERA_DEPS += axi_hdmi_tx_hw.tcl + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx.v b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx.v new file mode 100644 index 00000000..6eb75699 --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx.v @@ -0,0 +1,342 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_hdmi_tx #( + + parameter ID = 0, + parameter CR_CB_N = 0, + parameter DEVICE_TYPE = 0, + parameter INTERFACE = "16_BIT", + parameter OUT_CLK_POLARITY = 0) ( + + // hdmi interface + + input hdmi_clk, + output hdmi_out_clk, + + // 16-bit interface + + output hdmi_16_hsync, + output hdmi_16_vsync, + output hdmi_16_data_e, + output [15:0] hdmi_16_data, + output [15:0] hdmi_16_es_data, + + // 24-bit interface + + output hdmi_24_hsync, + output hdmi_24_vsync, + output hdmi_24_data_e, + output [23:0] hdmi_24_data, + + // 36-bit interface + + output hdmi_36_hsync, + output hdmi_36_vsync, + output hdmi_36_data_e, + output [35:0] hdmi_36_data, + + // vdma interface + + input vdma_clk, + input vdma_end_of_frame, + input vdma_valid, + input [63:0] vdma_data, + output vdma_ready, + + // axi interface + + input s_axi_aclk, + input s_axi_aresetn, + input s_axi_awvalid, + input [15:0] s_axi_awaddr, + input [ 2:0] s_axi_awprot, + output s_axi_awready, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [15:0] s_axi_araddr, + input [ 2:0] s_axi_arprot, + output s_axi_arready, + output s_axi_rvalid, + output [ 1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + input s_axi_rready); + + /* 0 = Launch on rising edge, 1 = Launch on falling edge */ + + localparam EMBEDDED_SYNC = (INTERFACE == "16_BIT_EMBEDDED_SYNC") ? 1 : 0; + localparam XILINX_7SERIES = 0; + localparam XILINX_ULTRASCALE = 1; + localparam ALTERA_5SERIES = 16; + + // reset and clocks + + wire up_rstn; + wire up_clk; + wire hdmi_rst; + wire vdma_rst; + + // internal signals + + wire up_wreq_s; + wire [13:0] up_waddr_s; + wire [31:0] up_wdata_s; + wire up_wack_s; + wire up_rreq_s; + wire [13:0] up_raddr_s; + wire [31:0] up_rdata_s; + wire up_rack_s; + wire hdmi_csc_bypass_s; + wire hdmi_ss_bypass_s; + wire [ 1:0] hdmi_srcsel_s; + wire [23:0] hdmi_const_rgb_s; + wire [15:0] hdmi_hl_active_s; + wire [15:0] hdmi_hl_width_s; + wire [15:0] hdmi_hs_width_s; + wire [15:0] hdmi_he_max_s; + wire [15:0] hdmi_he_min_s; + wire [15:0] hdmi_vf_active_s; + wire [15:0] hdmi_vf_width_s; + wire [15:0] hdmi_vs_width_s; + wire [15:0] hdmi_ve_max_s; + wire [15:0] hdmi_ve_min_s; + wire [23:0] hdmi_clip_max_s; + wire [23:0] hdmi_clip_min_s; + wire hdmi_fs_toggle_s; + wire [ 8:0] hdmi_raddr_g_s; + wire hdmi_tpm_oos_s; + wire hdmi_status_s; + wire vdma_wr_s; + wire [ 8:0] vdma_waddr_s; + wire [47:0] vdma_wdata_s; + wire vdma_fs_ret_toggle_s; + wire [ 8:0] vdma_fs_waddr_s; + wire vdma_ovf_s; + wire vdma_unf_s; + wire vdma_tpm_oos_s; + + // signal name changes + + assign up_rstn = s_axi_aresetn; + assign up_clk = s_axi_aclk; + + // axi interface + + up_axi i_up_axi ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_axi_awvalid (s_axi_awvalid), + .up_axi_awaddr (s_axi_awaddr), + .up_axi_awready (s_axi_awready), + .up_axi_wvalid (s_axi_wvalid), + .up_axi_wdata (s_axi_wdata), + .up_axi_wstrb (s_axi_wstrb), + .up_axi_wready (s_axi_wready), + .up_axi_bvalid (s_axi_bvalid), + .up_axi_bresp (s_axi_bresp), + .up_axi_bready (s_axi_bready), + .up_axi_arvalid (s_axi_arvalid), + .up_axi_araddr (s_axi_araddr), + .up_axi_arready (s_axi_arready), + .up_axi_rvalid (s_axi_rvalid), + .up_axi_rresp (s_axi_rresp), + .up_axi_rdata (s_axi_rdata), + .up_axi_rready (s_axi_rready), + .up_wreq (up_wreq_s), + .up_waddr (up_waddr_s), + .up_wdata (up_wdata_s), + .up_wack (up_wack_s), + .up_rreq (up_rreq_s), + .up_raddr (up_raddr_s), + .up_rdata (up_rdata_s), + .up_rack (up_rack_s)); + + // processor interface + + up_hdmi_tx i_up ( + .hdmi_clk (hdmi_clk), + .hdmi_rst (hdmi_rst), + .hdmi_csc_bypass (hdmi_csc_bypass_s), + .hdmi_ss_bypass (hdmi_ss_bypass_s), + .hdmi_srcsel (hdmi_srcsel_s), + .hdmi_const_rgb (hdmi_const_rgb_s), + .hdmi_hl_active (hdmi_hl_active_s), + .hdmi_hl_width (hdmi_hl_width_s), + .hdmi_hs_width (hdmi_hs_width_s), + .hdmi_he_max (hdmi_he_max_s), + .hdmi_he_min (hdmi_he_min_s), + .hdmi_vf_active (hdmi_vf_active_s), + .hdmi_vf_width (hdmi_vf_width_s), + .hdmi_vs_width (hdmi_vs_width_s), + .hdmi_ve_max (hdmi_ve_max_s), + .hdmi_ve_min (hdmi_ve_min_s), + .hdmi_clip_max (hdmi_clip_max_s), + .hdmi_clip_min (hdmi_clip_min_s), + .hdmi_status (hdmi_status_s), + .hdmi_tpm_oos (hdmi_tpm_oos_s), + .hdmi_clk_ratio (32'd1), + .vdma_clk (vdma_clk), + .vdma_rst (vdma_rst), + .vdma_ovf (vdma_ovf_s), + .vdma_unf (vdma_unf_s), + .vdma_tpm_oos (vdma_tpm_oos_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq_s), + .up_waddr (up_waddr_s), + .up_wdata (up_wdata_s), + .up_wack (up_wack_s), + .up_rreq (up_rreq_s), + .up_raddr (up_raddr_s), + .up_rdata (up_rdata_s), + .up_rack (up_rack_s)); + + // vdma interface + + axi_hdmi_tx_vdma i_vdma ( + .hdmi_fs_toggle (hdmi_fs_toggle_s), + .hdmi_raddr_g (hdmi_raddr_g_s), + .vdma_clk (vdma_clk), + .vdma_rst (vdma_rst), + .vdma_valid (vdma_valid), + .vdma_data (vdma_data), + .vdma_ready (vdma_ready), + .vdma_end_of_frame (vdma_end_of_frame), + .vdma_wr (vdma_wr_s), + .vdma_waddr (vdma_waddr_s), + .vdma_wdata (vdma_wdata_s), + .vdma_fs_ret_toggle (vdma_fs_ret_toggle_s), + .vdma_fs_waddr (vdma_fs_waddr_s), + .vdma_tpm_oos (vdma_tpm_oos_s), + .vdma_ovf (vdma_ovf_s), + .vdma_unf (vdma_unf_s)); + + // hdmi interface + + axi_hdmi_tx_core #( + .CR_CB_N(CR_CB_N), + .EMBEDDED_SYNC(EMBEDDED_SYNC)) + i_tx_core ( + .hdmi_clk (hdmi_clk), + .hdmi_rst (hdmi_rst), + .hdmi_16_hsync (hdmi_16_hsync), + .hdmi_16_vsync (hdmi_16_vsync), + .hdmi_16_data_e (hdmi_16_data_e), + .hdmi_16_data (hdmi_16_data), + .hdmi_16_es_data (hdmi_16_es_data), + .hdmi_24_hsync (hdmi_24_hsync), + .hdmi_24_vsync (hdmi_24_vsync), + .hdmi_24_data_e (hdmi_24_data_e), + .hdmi_24_data (hdmi_24_data), + .hdmi_36_hsync (hdmi_36_hsync), + .hdmi_36_vsync (hdmi_36_vsync), + .hdmi_36_data_e (hdmi_36_data_e), + .hdmi_36_data (hdmi_36_data), + .hdmi_fs_toggle (hdmi_fs_toggle_s), + .hdmi_raddr_g (hdmi_raddr_g_s), + .hdmi_tpm_oos (hdmi_tpm_oos_s), + .hdmi_status (hdmi_status_s), + .vdma_clk (vdma_clk), + .vdma_wr (vdma_wr_s), + .vdma_waddr (vdma_waddr_s), + .vdma_wdata (vdma_wdata_s), + .vdma_fs_ret_toggle (vdma_fs_ret_toggle_s), + .vdma_fs_waddr (vdma_fs_waddr_s), + .hdmi_csc_bypass (hdmi_csc_bypass_s), + .hdmi_ss_bypass (hdmi_ss_bypass_s), + .hdmi_srcsel (hdmi_srcsel_s), + .hdmi_const_rgb (hdmi_const_rgb_s), + .hdmi_hl_active (hdmi_hl_active_s), + .hdmi_hl_width (hdmi_hl_width_s), + .hdmi_hs_width (hdmi_hs_width_s), + .hdmi_he_max (hdmi_he_max_s), + .hdmi_he_min (hdmi_he_min_s), + .hdmi_vf_active (hdmi_vf_active_s), + .hdmi_vf_width (hdmi_vf_width_s), + .hdmi_vs_width (hdmi_vs_width_s), + .hdmi_ve_max (hdmi_ve_max_s), + .hdmi_ve_min (hdmi_ve_min_s), + .hdmi_clip_max (hdmi_clip_max_s), + .hdmi_clip_min (hdmi_clip_min_s)); + + // hdmi output clock + + generate + if (DEVICE_TYPE == XILINX_ULTRASCALE) begin + ODDRE1 #(.SRVAL(1'b0)) i_clk_oddr ( + .SR (1'b0), + .D1 (~OUT_CLK_POLARITY), + .D2 (OUT_CLK_POLARITY), + .C (hdmi_clk), + .Q (hdmi_out_clk)); + end + if (DEVICE_TYPE == ALTERA_5SERIES) begin + altddio_out #(.WIDTH(1)) i_clk_oddr ( + .aclr (1'b0), + .aset (1'b0), + .sclr (1'b0), + .sset (1'b0), + .oe (1'b1), + .outclocken (1'b1), + .datain_h (~OUT_CLK_POLARITY), + .datain_l (OUT_CLK_POLARITY), + .outclock (hdmi_clk), + .oe_out (), + .dataout (hdmi_out_clk)); + end + if (DEVICE_TYPE == XILINX_7SERIES) begin + ODDR #(.INIT(1'b0)) i_clk_oddr ( + .R (1'b0), + .S (1'b0), + .CE (1'b1), + .D1 (~OUT_CLK_POLARITY), + .D2 (OUT_CLK_POLARITY), + .C (hdmi_clk), + .Q (hdmi_out_clk)); + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.sdc b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.sdc new file mode 100644 index 00000000..7f715c9a --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.sdc @@ -0,0 +1,10 @@ + +set_false_path -from [get_registers *hdmi_fs_toggle*] -to [get_registers *vdma_fs_toggle_m1] +set_false_path -from [get_registers *hdmi_raddr_g*] -to [get_registers *vdma_raddr_g_m1*] +set_false_path -from [get_registers *vdma_fs_ret_toggle*] -to [get_registers *hdmi_fs_ret_toggle_m1] +set_false_path -from [get_registers *vdma_fs_waddr*] -to [get_registers *hdmi_fs_waddr*] + +set_false_path -from [get_registers *up_xfer_status:i_vdma_xfer_status|up_xfer_toggle*] -to [get_registers *up_xfer_status:i_vdma_xfer_status|d_xfer_state_m1*] +set_false_path -from [get_registers *up_xfer_status:i_vdma_xfer_status|d_xfer_toggle*] -to [get_registers *up_xfer_status:i_vdma_xfer_status|up_xfer_toggle_m1*] +set_false_path -from [get_registers *up_xfer_status:i_vdma_xfer_status|d_xfer_data*] -to [get_registers *up_xfer_status:i_vdma_xfer_status|up_data_status*] +set_false_path -from [get_registers *up_core_preset*] -to [get_registers *ad_rst_sync_m1] diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.xdc b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.xdc new file mode 100644 index 00000000..d7ab709a --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_constr.xdc @@ -0,0 +1,10 @@ + +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *vdma_fs_toggle*}] +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *vdma_raddr_g*}] +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *hdmi_fs_ret_toggle*}] + +set_false_path -from [get_cells -hier -filter {name =~ *hdmi_fs_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *vdma_fs_toggle_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *hdmi_raddr_g* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *vdma_raddr_g_m1* && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *vdma_fs_ret_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *hdmi_fs_ret_toggle_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *vdma_fs_waddr* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *hdmi_fs_waddr* && IS_SEQUENTIAL}] + diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_core.v b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_core.v new file mode 100644 index 00000000..8191cf6b --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_core.v @@ -0,0 +1,572 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Transmit HDMI, video dma data in, hdmi separate syncs data out. + +`timescale 1ns/100ps + +module axi_hdmi_tx_core #( + + parameter CR_CB_N = 0, + parameter EMBEDDED_SYNC = 0) ( + + // hdmi interface + + input hdmi_clk, + input hdmi_rst, + + // 16-bit interface + + output reg hdmi_16_hsync, + output reg hdmi_16_vsync, + output reg hdmi_16_data_e, + output reg [15:0] hdmi_16_data, + output reg [15:0] hdmi_16_es_data, + + // 24-bit interface + + output reg hdmi_24_hsync, + output reg hdmi_24_vsync, + output reg hdmi_24_data_e, + output reg [23:0] hdmi_24_data, + + // 36-bit interface + + output reg hdmi_36_hsync, + output reg hdmi_36_vsync, + output reg hdmi_36_data_e, + output reg [35:0] hdmi_36_data, + + // control signals + + output reg hdmi_fs_toggle, + output reg [ 8:0] hdmi_raddr_g, + output reg hdmi_tpm_oos, + output reg hdmi_status, + + // vdma interface + + input vdma_clk, + input vdma_wr, + input [ 8:0] vdma_waddr, + input [47:0] vdma_wdata, + input vdma_fs_ret_toggle, + input [ 8:0] vdma_fs_waddr, + + // processor interface + + input hdmi_csc_bypass, + input hdmi_ss_bypass, + input [ 1:0] hdmi_srcsel, + input [23:0] hdmi_const_rgb, + input [15:0] hdmi_hl_active, + input [15:0] hdmi_hl_width, + input [15:0] hdmi_hs_width, + input [15:0] hdmi_he_max, + input [15:0] hdmi_he_min, + input [15:0] hdmi_vf_active, + input [15:0] hdmi_vf_width, + input [15:0] hdmi_vs_width, + input [15:0] hdmi_ve_max, + input [15:0] hdmi_ve_min, + input [23:0] hdmi_clip_max, + input [23:0] hdmi_clip_min); + + + // internal registers + + reg hdmi_enable = 'd0; + reg [15:0] hdmi_hs_count = 'd0; + reg [15:0] hdmi_vs_count = 'd0; + reg hdmi_fs = 'd0; + reg hdmi_fs_ret_toggle_m1 = 'd0; + reg hdmi_fs_ret_toggle_m2 = 'd0; + reg hdmi_fs_ret_toggle_m3 = 'd0; + reg hdmi_fs_ret = 'd0; + reg [ 8:0] hdmi_fs_waddr = 'd0; + reg hdmi_hs = 'd0; + reg hdmi_vs = 'd0; + reg hdmi_hs_de = 'd0; + reg hdmi_vs_de = 'd0; + reg [ 9:0] hdmi_raddr = 'd0; + reg hdmi_hs_d = 'd0; + reg hdmi_vs_d = 'd0; + reg hdmi_hs_de_d = 'd0; + reg hdmi_vs_de_d = 'd0; + reg hdmi_de_d = 'd0; + reg hdmi_data_sel_d = 'd0; + reg hdmi_hs_2d = 'd0; + reg hdmi_vs_2d = 'd0; + reg hdmi_hs_de_2d = 'd0; + reg hdmi_vs_de_2d = 'd0; + reg hdmi_de_2d = 'd0; + reg hdmi_data_sel_2d = 'd0; + reg [47:0] hdmi_data_2d = 'd0; + reg [23:0] hdmi_tpm_data = 'd0; + reg hdmi_hsync = 'd0; + reg hdmi_vsync = 'd0; + reg hdmi_hsync_data_e = 'd0; + reg hdmi_vsync_data_e = 'd0; + reg hdmi_data_e = 'd0; + reg [23:0] hdmi_data = 'd0; + reg hdmi_24_csc_hsync = 'd0; + reg hdmi_24_csc_vsync = 'd0; + reg hdmi_24_csc_hsync_data_e = 'd0; + reg hdmi_24_csc_vsync_data_e = 'd0; + reg hdmi_24_csc_data_e = 'd0; + reg [23:0] hdmi_24_csc_data = 'd0; + reg hdmi_16_hsync_d = 'd0; + reg hdmi_16_vsync_d = 'd0; + reg hdmi_16_hsync_data_e_d = 'd0; + reg hdmi_16_vsync_data_e_d = 'd0; + reg hdmi_16_data_e_d = 'd0; + reg [15:0] hdmi_16_data_d = 'd0; + reg hdmi_es_hs_de = 'd0; + reg hdmi_es_vs_de = 'd0; + reg [15:0] hdmi_es_data = 'd0; + reg [23:0] hdmi_clip_data = 'd0; + reg hdmi_clip_hs_de_d = 'd0; + reg hdmi_clip_vs_de_d = 'd0; + reg hdmi_clip_hs_d = 'd0; + reg hdmi_clip_vs_d = 'd0; + reg hdmi_clip_de_d = 'd0; + + // internal wires + + wire [15:0] hdmi_hl_width_s; + wire [15:0] hdmi_vf_width_s; + wire [15:0] hdmi_he_width_s; + wire [15:0] hdmi_ve_width_s; + wire hdmi_fs_ret_s; + wire hdmi_de_s; + wire [47:0] hdmi_rdata_s; + wire [23:0] hdmi_data_2d_s; + wire hdmi_tpm_mismatch_s; + wire [23:0] hdmi_tpg_data_s; + wire hdmi_csc_hsync_s; + wire hdmi_csc_vsync_s; + wire hdmi_csc_hsync_data_e_s; + wire hdmi_csc_vsync_data_e_s; + wire hdmi_csc_data_e_s; + wire [23:0] hdmi_csc_data_s; + wire hdmi_ss_hsync_s; + wire hdmi_ss_vsync_s; + wire hdmi_ss_hsync_data_e_s; + wire hdmi_ss_vsync_data_e_s; + wire hdmi_ss_data_e_s; + wire [15:0] hdmi_ss_data_s; + wire [15:0] hdmi_es_data_s; + + // binary to grey conversion + + function [8:0] b2g; + input [8:0] b; + reg [8:0] g; + begin + g[8] = b[8]; + g[7] = b[8] ^ b[7]; + g[6] = b[7] ^ b[6]; + g[5] = b[6] ^ b[5]; + g[4] = b[5] ^ b[4]; + g[3] = b[4] ^ b[3]; + g[2] = b[3] ^ b[2]; + g[1] = b[2] ^ b[1]; + g[0] = b[1] ^ b[0]; + b2g = g; + end + endfunction + + // status and enable + + always @(posedge hdmi_clk) begin + if (hdmi_rst == 1'b1) begin + hdmi_status <= 1'b0; + hdmi_enable <= 1'b0; + end else begin + hdmi_status <= 1'b1; + hdmi_enable <= hdmi_srcsel[1] | hdmi_srcsel[0]; + end + end + + // calculate useful limits + + assign hdmi_hl_width_s = hdmi_hl_width - 1'b1; + assign hdmi_vf_width_s = hdmi_vf_width - 1'b1; + assign hdmi_he_width_s = hdmi_hl_width - (hdmi_hl_active + 1'b1); + assign hdmi_ve_width_s = hdmi_vf_width - (hdmi_vf_active + 1'b1); + + // hdmi counters + + always @(posedge hdmi_clk) begin + if (hdmi_hs_count >= hdmi_hl_width_s) begin + hdmi_hs_count <= 0; + end else begin + hdmi_hs_count <= hdmi_hs_count + 1'b1; + end + if (hdmi_hs_count >= hdmi_hl_width_s) begin + if (hdmi_vs_count >= hdmi_vf_width_s) begin + hdmi_vs_count <= 0; + end else begin + hdmi_vs_count <= hdmi_vs_count + 1'b1; + end + end + end + + // hdmi start of frame + + always @(posedge hdmi_clk) begin + if (hdmi_rst == 1'b1) begin + hdmi_fs_toggle <= 1'b0; + hdmi_fs <= 1'b0; + end else begin + if (EMBEDDED_SYNC == 1) begin + if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_ve_width_s)) begin + hdmi_fs <= hdmi_enable; + end else begin + hdmi_fs <= 1'b0; + end + end else begin + if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_vs_width)) begin + hdmi_fs <= hdmi_enable; + end else begin + hdmi_fs <= 1'b0; + end + end + if (hdmi_fs == 1'b1) begin + hdmi_fs_toggle <= ~hdmi_fs_toggle; + end + end + end + + // hdmi sof write address + + assign hdmi_fs_ret_s = hdmi_fs_ret_toggle_m2 ^ hdmi_fs_ret_toggle_m3; + + always @(posedge hdmi_clk or posedge hdmi_rst) begin + if (hdmi_rst == 1'b1) begin + hdmi_fs_ret_toggle_m1 <= 1'd0; + hdmi_fs_ret_toggle_m2 <= 1'd0; + hdmi_fs_ret_toggle_m3 <= 1'd0; + end else begin + hdmi_fs_ret_toggle_m1 <= vdma_fs_ret_toggle; + hdmi_fs_ret_toggle_m2 <= hdmi_fs_ret_toggle_m1; + hdmi_fs_ret_toggle_m3 <= hdmi_fs_ret_toggle_m2; + end + end + + always @(posedge hdmi_clk) begin + hdmi_fs_ret <= hdmi_fs_ret_s; + hdmi_fs_waddr <= vdma_fs_waddr; + end + + // hdmi sync signals + + always @(posedge hdmi_clk) begin + if (EMBEDDED_SYNC == 1) begin + hdmi_hs <= 1'b0; + hdmi_vs <= 1'b0; + if (hdmi_hs_count <= hdmi_he_width_s) begin + hdmi_hs_de <= 1'b0; + end else begin + hdmi_hs_de <= hdmi_enable; + end + if (hdmi_vs_count <= hdmi_ve_width_s) begin + hdmi_vs_de <= 1'b0; + end else begin + hdmi_vs_de <= hdmi_enable; + end + end else begin + if (hdmi_hs_count < hdmi_hs_width) begin + hdmi_hs <= hdmi_enable; + end else begin + hdmi_hs <= 1'b0; + end + if (hdmi_vs_count < hdmi_vs_width) begin + hdmi_vs <= hdmi_enable; + end else begin + hdmi_vs <= 1'b0; + end + if ((hdmi_hs_count < hdmi_he_min) || (hdmi_hs_count >= hdmi_he_max)) begin + hdmi_hs_de <= 1'b0; + end else begin + hdmi_hs_de <= hdmi_enable; + end + if ((hdmi_vs_count < hdmi_ve_min) || (hdmi_vs_count >= hdmi_ve_max)) begin + hdmi_vs_de <= 1'b0; + end else begin + hdmi_vs_de <= hdmi_enable; + end + end + end + + // hdmi read data + + assign hdmi_de_s = hdmi_hs_de & hdmi_vs_de; + + always @(posedge hdmi_clk) begin + if (hdmi_rst == 1'b1) begin + hdmi_raddr <= 10'd0; + end else if (hdmi_fs == 1'b1) begin + hdmi_raddr <= {hdmi_fs_waddr, 1'b0}; + end else if (hdmi_de_s == 1'b1) begin + hdmi_raddr <= hdmi_raddr + 1'b1; + end + hdmi_raddr_g <= b2g(hdmi_raddr[9:1]); + end + + // control and data pipe line + + always @(posedge hdmi_clk) begin + hdmi_hs_d <= hdmi_hs; + hdmi_vs_d <= hdmi_vs; + hdmi_hs_de_d <= hdmi_hs_de; + hdmi_vs_de_d <= hdmi_vs_de; + hdmi_de_d <= hdmi_de_s; + hdmi_data_sel_d <= hdmi_raddr[0]; + hdmi_hs_2d <= hdmi_hs_d; + hdmi_vs_2d <= hdmi_vs_d; + hdmi_hs_de_2d <= hdmi_hs_de_d; + hdmi_vs_de_2d <= hdmi_vs_de_d; + hdmi_de_2d <= hdmi_de_d; + hdmi_data_sel_2d <= hdmi_data_sel_d; + hdmi_data_2d <= hdmi_rdata_s; + end + + // hdmi data count (may be used to monitor or insert) + + assign hdmi_data_2d_s = (hdmi_data_sel_2d == 1'b1) ? hdmi_data_2d[47:24] : hdmi_data_2d[23:0]; + assign hdmi_tpm_mismatch_s = (hdmi_data_2d_s == hdmi_tpm_data) ? 1'b0 : hdmi_de_2d; + assign hdmi_tpg_data_s = hdmi_tpm_data; + + always @(posedge hdmi_clk) begin + if ((hdmi_rst == 1'b1) || (hdmi_fs_ret == 1'b1)) begin + hdmi_tpm_data <= 'd0; + end else if (hdmi_de_2d == 1'b1) begin + hdmi_tpm_data <= hdmi_tpm_data + 1'b1; + end + hdmi_tpm_oos <= hdmi_tpm_mismatch_s; + end + + // hdmi data select + + always @(posedge hdmi_clk) begin + hdmi_hsync <= hdmi_hs_2d; + hdmi_vsync <= hdmi_vs_2d; + hdmi_hsync_data_e <= hdmi_hs_de_2d; + hdmi_vsync_data_e <= hdmi_vs_de_2d; + hdmi_data_e <= hdmi_de_2d; + case (hdmi_srcsel) + 2'b11: hdmi_data <= hdmi_const_rgb; + 2'b10: hdmi_data <= hdmi_tpg_data_s; + 2'b01: hdmi_data <= hdmi_data_2d_s; + default: hdmi_data <= 24'd0; + endcase + end + + // Color space conversion bypass (RGB/YCbCr) + + always @(posedge hdmi_clk) begin + if (hdmi_csc_bypass == 1'b1) begin + hdmi_24_csc_hsync <= hdmi_hsync; + hdmi_24_csc_vsync <= hdmi_vsync; + hdmi_24_csc_hsync_data_e <= hdmi_hsync_data_e; + hdmi_24_csc_vsync_data_e <= hdmi_vsync_data_e; + hdmi_24_csc_data_e <= hdmi_data_e; + hdmi_24_csc_data <= hdmi_data; + end else begin + hdmi_24_csc_hsync <= hdmi_csc_hsync_s; + hdmi_24_csc_vsync <= hdmi_csc_vsync_s; + hdmi_24_csc_hsync_data_e <= hdmi_csc_hsync_data_e_s; + hdmi_24_csc_vsync_data_e <= hdmi_csc_vsync_data_e_s; + hdmi_24_csc_data_e <= hdmi_csc_data_e_s; + hdmi_24_csc_data <= hdmi_csc_data_s; + end + end + + // hdmi clipping + + always @(posedge hdmi_clk) begin + hdmi_clip_hs_d <= hdmi_24_csc_hsync; + hdmi_clip_vs_d <= hdmi_24_csc_vsync; + hdmi_clip_hs_de_d <= hdmi_24_csc_hsync_data_e; + hdmi_clip_vs_de_d <= hdmi_24_csc_vsync_data_e; + hdmi_clip_de_d <= hdmi_24_csc_data_e; + + // Cr (red-diff) / red + + if (hdmi_24_csc_data[23:16] > hdmi_clip_max[23:16]) begin + hdmi_clip_data[23:16] <= hdmi_clip_max[23:16]; + end else if (hdmi_24_csc_data[23:16] < hdmi_clip_min[23:16]) begin + hdmi_clip_data[23:16] <= hdmi_clip_min[23:16]; + end else begin + hdmi_clip_data[23:16] <= hdmi_24_csc_data[23:16]; + end + + // Y (luma) / green + + if (hdmi_24_csc_data[15:8] > hdmi_clip_max[15:8]) begin + hdmi_clip_data[15:8] <= hdmi_clip_max[15:8]; + end else if (hdmi_24_csc_data[15:8] < hdmi_clip_min[15:8]) begin + hdmi_clip_data[15:8] <= hdmi_clip_min[15:8]; + end else begin + hdmi_clip_data[15:8] <= hdmi_24_csc_data[15:8]; + end + + // Cb (blue-diff) / blue + + if (hdmi_24_csc_data[7:0] > hdmi_clip_max[7:0]) begin + hdmi_clip_data[7:0] <= hdmi_clip_max[7:0]; + end else if (hdmi_24_csc_data[7:0] < hdmi_clip_min[7:0]) begin + hdmi_clip_data[7:0] <= hdmi_clip_min[7:0]; + end else begin + hdmi_clip_data[7:0] <= hdmi_24_csc_data[7:0]; + end + end + + // hdmi csc 16, 24 and 36 outputs + + always @(posedge hdmi_clk) begin + + hdmi_36_hsync <= hdmi_clip_hs_d; + hdmi_36_vsync <= hdmi_clip_vs_d; + hdmi_36_data_e <= hdmi_clip_de_d; + hdmi_36_data[35:24] <= {hdmi_clip_data[23:16], hdmi_clip_data[23:20]}; + hdmi_36_data[23:12] <= {hdmi_clip_data[15: 8], hdmi_clip_data[15:12]}; + hdmi_36_data[11: 0] <= {hdmi_clip_data[ 7: 0], hdmi_clip_data[ 7: 4]}; + + hdmi_24_hsync <= hdmi_clip_hs_d; + hdmi_24_vsync <= hdmi_clip_vs_d; + hdmi_24_data_e <= hdmi_clip_de_d; + hdmi_24_data <= hdmi_clip_data; + + hdmi_16_hsync <= hdmi_16_hsync_d; + hdmi_16_vsync <= hdmi_16_vsync_d; + hdmi_16_data_e <= hdmi_16_data_e_d; + hdmi_16_data <= hdmi_16_data_d; + hdmi_16_es_data <= hdmi_es_data_s; + + if (hdmi_ss_bypass == 1'b1) begin + hdmi_16_hsync_d <= hdmi_clip_hs_d; + hdmi_16_vsync_d <= hdmi_clip_vs_d; + hdmi_16_hsync_data_e_d <= hdmi_clip_hs_de_d; + hdmi_16_vsync_data_e_d <= hdmi_clip_vs_de_d; + hdmi_16_data_e_d <= hdmi_clip_de_d; + hdmi_16_data_d <= hdmi_clip_data[15:0]; // Ignore the upper 8 bit + end else begin + hdmi_16_hsync_d <= hdmi_ss_hsync_s; + hdmi_16_vsync_d <= hdmi_ss_vsync_s; + hdmi_16_hsync_data_e_d <= hdmi_ss_hsync_data_e_s; + hdmi_16_vsync_data_e_d <= hdmi_ss_vsync_data_e_s; + hdmi_16_data_e_d <= hdmi_ss_data_e_s; + hdmi_16_data_d <= hdmi_ss_data_s; + end + end + + // hdmi embedded sync + + always @(posedge hdmi_clk) begin + hdmi_es_hs_de <= hdmi_16_hsync_data_e_d; + hdmi_es_vs_de <= hdmi_16_vsync_data_e_d; + if (hdmi_16_data_e_d == 1'b0) begin + hdmi_es_data[15:8] <= 8'h80; + end else begin + hdmi_es_data[15:8] <= hdmi_16_data_d[15:8]; + end + if (hdmi_16_data_e_d == 1'b0) begin + hdmi_es_data[7:0] <= 8'h80; + end else begin + hdmi_es_data[7:0] <= hdmi_16_data_d[7:0]; + end + end + + // data memory + + ad_mem #(.DATA_WIDTH(48), .ADDRESS_WIDTH(9)) i_mem ( + .clka (vdma_clk), + .wea (vdma_wr), + .addra (vdma_waddr), + .dina (vdma_wdata), + .clkb (hdmi_clk), + .reb (1'b1), + .addrb (hdmi_raddr[9:1]), + .doutb (hdmi_rdata_s)); + + // color space coversion, RGB to CrYCb + + ad_csc_RGB2CrYCb #(.DELAY_DATA_WIDTH(5)) i_csc_RGB2CrYCb ( + .clk (hdmi_clk), + .RGB_sync ({hdmi_hsync, + hdmi_vsync, + hdmi_hsync_data_e, + hdmi_vsync_data_e, + hdmi_data_e}), + .RGB_data (hdmi_data), + .CrYCb_sync ({hdmi_csc_hsync_s, + hdmi_csc_vsync_s, + hdmi_csc_hsync_data_e_s, + hdmi_csc_vsync_data_e_s, + hdmi_csc_data_e_s}), + .CrYCb_data (hdmi_csc_data_s)); + + // sub sampling, 444 to 422 + + ad_ss_444to422 #(.DELAY_DATA_WIDTH(5), .CR_CB_N(CR_CB_N)) i_ss_444to422 ( + .clk (hdmi_clk), + .s444_de (hdmi_clip_de_d), + .s444_sync ({hdmi_clip_hs_d, + hdmi_clip_vs_d, + hdmi_clip_hs_de_d, + hdmi_clip_vs_de_d, + hdmi_clip_de_d}), + .s444_data (hdmi_clip_data), + .s422_sync ({hdmi_ss_hsync_s, + hdmi_ss_vsync_s, + hdmi_ss_hsync_data_e_s, + hdmi_ss_vsync_data_e_s, + hdmi_ss_data_e_s}), + .s422_data (hdmi_ss_data_s)); + + // embedded sync + + axi_hdmi_tx_es #(.DATA_WIDTH(16)) i_es ( + .hdmi_clk (hdmi_clk), + .hdmi_hs_de (hdmi_es_hs_de), + .hdmi_vs_de (hdmi_es_vs_de), + .hdmi_data_de (hdmi_es_data), + .hdmi_data (hdmi_es_data_s)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_es.v b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_es.v new file mode 100644 index 00000000..feaae2cd --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_es.v @@ -0,0 +1,107 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Transmit HDMI, video dma data in, hdmi separate syncs data out. + +`timescale 1ns/100ps + +module axi_hdmi_tx_es #( + + parameter DATA_WIDTH = 32) ( + + // hdmi interface + + input hdmi_clk, + input hdmi_hs_de, + input hdmi_vs_de, + input [(DATA_WIDTH-1):0] hdmi_data_de, + output reg [(DATA_WIDTH-1):0] hdmi_data); + + localparam BYTE_WIDTH = DATA_WIDTH/8; + + // internal registers + + reg hdmi_hs_de_d = 'd0; + reg [(DATA_WIDTH-1):0] hdmi_data_d = 'd0; + reg hdmi_hs_de_2d = 'd0; + reg [(DATA_WIDTH-1):0] hdmi_data_2d = 'd0; + reg hdmi_hs_de_3d = 'd0; + reg [(DATA_WIDTH-1):0] hdmi_data_3d = 'd0; + reg hdmi_hs_de_4d = 'd0; + reg [(DATA_WIDTH-1):0] hdmi_data_4d = 'd0; + reg hdmi_hs_de_5d = 'd0; + reg [(DATA_WIDTH-1):0] hdmi_data_5d = 'd0; + + // internal wires + + wire [(DATA_WIDTH-1):0] hdmi_sav_s; + wire [(DATA_WIDTH-1):0] hdmi_eav_s; + + // hdmi embedded sync insertion + + assign hdmi_sav_s = (hdmi_vs_de == 1) ? {BYTE_WIDTH{8'h80}} : {BYTE_WIDTH{8'hab}}; + assign hdmi_eav_s = (hdmi_vs_de == 1) ? {BYTE_WIDTH{8'h9d}} : {BYTE_WIDTH{8'hb6}}; + + always @(posedge hdmi_clk) begin + hdmi_hs_de_d <= hdmi_hs_de; + case ({hdmi_hs_de_4d, hdmi_hs_de_3d, hdmi_hs_de_2d, + hdmi_hs_de_d, hdmi_hs_de}) + 5'b11000: hdmi_data_d <= {BYTE_WIDTH{8'h00}}; + 5'b11100: hdmi_data_d <= {BYTE_WIDTH{8'h00}}; + 5'b11110: hdmi_data_d <= {BYTE_WIDTH{8'hff}}; + 5'b10000: hdmi_data_d <= hdmi_eav_s; + default: hdmi_data_d <= hdmi_data_de; + endcase + hdmi_hs_de_2d <= hdmi_hs_de_d; + hdmi_data_2d <= hdmi_data_d; + hdmi_hs_de_3d <= hdmi_hs_de_2d; + hdmi_data_3d <= hdmi_data_2d; + hdmi_hs_de_4d <= hdmi_hs_de_3d; + hdmi_data_4d <= hdmi_data_3d; + hdmi_hs_de_5d <= hdmi_hs_de_4d; + hdmi_data_5d <= hdmi_data_4d; + case ({hdmi_hs_de_5d, hdmi_hs_de_4d, hdmi_hs_de_3d, + hdmi_hs_de_2d, hdmi_hs_de_d}) + 5'b00111: hdmi_data <= {BYTE_WIDTH{8'h00}}; + 5'b00011: hdmi_data <= {BYTE_WIDTH{8'h00}}; + 5'b00001: hdmi_data <= {BYTE_WIDTH{8'hff}}; + 5'b01111: hdmi_data <= hdmi_sav_s; + default: hdmi_data <= hdmi_data_5d; + endcase + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_hw.tcl b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_hw.tcl new file mode 100644 index 00000000..15fbb9bf --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_hw.tcl @@ -0,0 +1,104 @@ + + +package require qsys +source ../scripts/adi_env.tcl +source ../scripts/adi_ip_alt.tcl + +set_module_property NAME axi_hdmi_tx +set_module_property DESCRIPTION "AXI HDMI Transmit Interface" +set_module_property VERSION 1.0 +set_module_property GROUP "Analog Devices" +set_module_property DISPLAY_NAME axi_hdmi_tx + +# files + +add_fileset quartus_synth QUARTUS_SYNTH "" "Quartus Synthesis" +set_fileset_property quartus_synth TOP_LEVEL axi_hdmi_tx +add_fileset_file ad_mem.v VERILOG PATH $ad_hdl_dir/library/common/ad_mem.v +add_fileset_file ad_rst.v VERILOG PATH $ad_hdl_dir/library/common/ad_rst.v +add_fileset_file ad_csc_1_mul.v VERILOG PATH $ad_hdl_dir/library/common/ad_csc_1_mul.v +add_fileset_file ad_csc_1_add.v VERILOG PATH $ad_hdl_dir/library/common/ad_csc_1_add.v +add_fileset_file ad_csc_1.v VERILOG PATH $ad_hdl_dir/library/common/ad_csc_1.v +add_fileset_file ad_csc_RGB2CrYCb.v VERILOG PATH $ad_hdl_dir/library/common/ad_csc_RGB2CrYCb.v +add_fileset_file ad_ss_444to422.v VERILOG PATH $ad_hdl_dir/library/common/ad_ss_444to422.v +add_fileset_file up_axi.v VERILOG PATH $ad_hdl_dir/library/common/up_axi.v +add_fileset_file up_xfer_cntrl.v VERILOG PATH $ad_hdl_dir/library/common/up_xfer_cntrl.v +add_fileset_file up_xfer_status.v VERILOG PATH $ad_hdl_dir/library/common/up_xfer_status.v +add_fileset_file up_clock_mon.v VERILOG PATH $ad_hdl_dir/library/common/up_clock_mon.v +add_fileset_file up_hdmi_tx.v VERILOG PATH $ad_hdl_dir/library/common/up_hdmi_tx.v +add_fileset_file ad_mul.v VERILOG PATH $ad_hdl_dir/library/altera/common/ad_mul.v +add_fileset_file axi_hdmi_tx_vdma.v VERILOG PATH axi_hdmi_tx_vdma.v +add_fileset_file axi_hdmi_tx_es.v VERILOG PATH axi_hdmi_tx_es.v +add_fileset_file axi_hdmi_tx_core.v VERILOG PATH axi_hdmi_tx_core.v +add_fileset_file axi_hdmi_tx.v VERILOG PATH axi_hdmi_tx.v TOP_LEVEL_FILE +add_fileset_file up_xfer_cntrl_constr.sdc SDC PATH $ad_hdl_dir/library/altera/common/up_xfer_cntrl_constr.sdc +add_fileset_file up_xfer_status_constr.sdc SDC PATH $ad_hdl_dir/library/altera/common/up_xfer_status_constr.sdc +add_fileset_file up_clock_mon_constr.sdc SDC PATH $ad_hdl_dir/library/altera/common/up_clock_mon_constr.sdc +add_fileset_file up_rst_constr.sdc SDC PATH $ad_hdl_dir/library/altera/common/up_rst_constr.sdc +add_fileset_file axi_hdmi_tx_constr.sdc SDC PATH axi_hdmi_tx_constr.sdc + +# parameters + +add_parameter ID INTEGER 0 +set_parameter_property ID DEFAULT_VALUE 0 +set_parameter_property ID DISPLAY_NAME ID +set_parameter_property ID TYPE INTEGER +set_parameter_property ID UNITS None +set_parameter_property ID HDL_PARAMETER true + +add_parameter CR_CB_N INTEGER 0 +set_parameter_property CR_CB_N DEFAULT_VALUE 0 +set_parameter_property CR_CB_N DISPLAY_NAME CR_CB_N +set_parameter_property CR_CB_N TYPE INTEGER +set_parameter_property CR_CB_N UNITS None +set_parameter_property CR_CB_N HDL_PARAMETER true + +add_parameter DEVICE_TYPE INTEGER 0 +set_parameter_property DEVICE_TYPE DEFAULT_VALUE 16 +set_parameter_property DEVICE_TYPE DISPLAY_NAME DEVICE_TYPE +set_parameter_property DEVICE_TYPE TYPE INTEGER +set_parameter_property DEVICE_TYPE UNITS None +set_parameter_property DEVICE_TYPE HDL_PARAMETER true + +add_parameter EMBEDDED_SYNC INTEGER 0 +set_parameter_property EMBEDDED_SYNC DEFAULT_VALUE 0 +set_parameter_property EMBEDDED_SYNC DISPLAY_NAME EMBEDDED_SYNC +set_parameter_property EMBEDDED_SYNC TYPE INTEGER +set_parameter_property EMBEDDED_SYNC UNITS None +set_parameter_property EMBEDDED_SYNC HDL_PARAMETER true + +# axi4 slave + +ad_ip_intf_s_axi s_axi_aclk s_axi_aresetn + +# hdmi interface + +add_interface hdmi_clock clock end +add_interface_port hdmi_clock hdmi_clk clk Input 1 + +add_interface hdmi_if conduit end +set_interface_property hdmi_if associatedClock hdmi_clock +add_interface_port hdmi_if hdmi_out_clk h_clk Output 1 +add_interface_port hdmi_if hdmi_16_hsync h16_hsync Output 1 +add_interface_port hdmi_if hdmi_16_vsync h16_vsync Output 1 +add_interface_port hdmi_if hdmi_16_data_e h16_data_e Output 1 +add_interface_port hdmi_if hdmi_16_data h16_data Output 16 +add_interface_port hdmi_if hdmi_16_es_data h16_es_data Output 16 +add_interface_port hdmi_if hdmi_24_hsync h24_hsync Output 1 +add_interface_port hdmi_if hdmi_24_vsync h24_vsync Output 1 +add_interface_port hdmi_if hdmi_24_data_e h24_data_e Output 1 +add_interface_port hdmi_if hdmi_24_data h24_data Output 24 +add_interface_port hdmi_if hdmi_36_hsync h36_hsync Output 1 +add_interface_port hdmi_if hdmi_36_vsync h36_vsync Output 1 +add_interface_port hdmi_if hdmi_36_data_e h36_data_e Output 1 +add_interface_port hdmi_if hdmi_36_data h36_data Output 36 + +# avalon streaming dma + +add_interface vdma_clock clock end +add_interface_port vdma_clock vdma_clk clk Input 1 + +ad_alt_intf signal vdma_ready output 1 ready +ad_alt_intf signal vdma_valid input 1 valid +ad_alt_intf signal vdma_data input 64 data +ad_alt_intf signal vdma_end_of_frame input 1 last diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_ip.tcl b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_ip.tcl new file mode 100644 index 00000000..6b42f6e2 --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_ip.tcl @@ -0,0 +1,72 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_hdmi_tx +adi_ip_files axi_hdmi_tx [list \ + "$ad_hdl_dir/library/common/ad_mem.v" \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/common/ad_csc_1_mul.v" \ + "$ad_hdl_dir/library/common/ad_csc_1_add.v" \ + "$ad_hdl_dir/library/common/ad_csc_1.v" \ + "$ad_hdl_dir/library/common/ad_csc_RGB2CrYCb.v" \ + "$ad_hdl_dir/library/common/ad_ss_444to422.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/common/up_xfer_cntrl.v" \ + "$ad_hdl_dir/library/common/up_xfer_status.v" \ + "$ad_hdl_dir/library/common/up_clock_mon.v" \ + "$ad_hdl_dir/library/common/up_hdmi_tx.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_mul.v" \ + "$ad_hdl_dir/library/xilinx/common/up_xfer_cntrl_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/ad_rst_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/up_xfer_status_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/up_clock_mon_constr.xdc" \ + "axi_hdmi_tx_constr.xdc" \ + "axi_hdmi_tx_vdma.v" \ + "axi_hdmi_tx_es.v" \ + "axi_hdmi_tx_core.v" \ + "axi_hdmi_tx.v" ] + +adi_ip_properties axi_hdmi_tx + +set_property driver_value 0 [ipx::get_ports *hsync* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *vsync* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *data* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *es_data* -of_objects [ipx::current_core]] + +set_property driver_value 0 [ipx::get_ports *vdma_end_of_frame* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *vdma_valid* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *vdma_data* -of_objects [ipx::current_core]] +set_property driver_value 0 [ipx::get_ports *vdma_ready* -of_objects [ipx::current_core]] + +set_property value_format string [ipx::get_user_parameters INTERFACE -of_objects [ipx::current_core]] +set_property value_format string [ipx::get_hdl_parameters INTERFACE -of_objects [ipx::current_core]] +set_property value_validation_list {16_BIT 24_BIT 36_BIT 16_BIT_EMBEDDED_SYNC} \ + [ipx::get_user_parameters INTERFACE -of_objects [ipx::current_core]] + +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INTERFACE')) == "16_BIT"} \ + [ipx::get_ports *hdmi_16* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INTERFACE')) == "24_BIT"} \ + [ipx::get_ports *hdmi_24* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INTERFACE')) == "36_BIT"} \ + [ipx::get_ports *hdmi_36* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INTERFACE')) == "16_BIT_EMBEDDED_SYNC"} \ + [ipx::get_ports *hdmi_16_es_data* -of_objects [ipx::current_core]] + +adi_add_bus "s_axis" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"vdma_ready" "TREADY"} \ + {"vdma_valid" "TVALID"} \ + {"vdma_data" "TDATA"} \ + {"vdma_end_of_frame" "TLAST"} ] + +ipx::infer_bus_interface hdmi_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface hdmi_out_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface vdma_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] + +ipx::associate_bus_interfaces -busif s_axis -clock vdma_clk [ipx::current_core] + +ipx::save_core [ipx::current_core] + diff --git a/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_vdma.v b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_vdma.v new file mode 100644 index 00000000..4db00e13 --- /dev/null +++ b/src/adi/hdl/library/axi_hdmi_tx/axi_hdmi_tx_vdma.v @@ -0,0 +1,235 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Transmit HDMI, video dma data in, hdmi separate syncs data out. + +`timescale 1ns/100ps + +module axi_hdmi_tx_vdma ( + + // hdmi interface + + input hdmi_fs_toggle, + input [ 8:0] hdmi_raddr_g, + + // vdma interface + + input vdma_clk, + input vdma_rst, + input vdma_end_of_frame, + input vdma_valid, + input [63:0] vdma_data, + output reg vdma_ready, + output reg vdma_wr, + output reg [ 8:0] vdma_waddr, + output reg [47:0] vdma_wdata, + output reg vdma_fs_ret_toggle, + output reg [ 8:0] vdma_fs_waddr, + output reg vdma_tpm_oos, + output reg vdma_ovf, + output reg vdma_unf); + + localparam BUF_THRESHOLD_LO = 9'd3; + localparam BUF_THRESHOLD_HI = 9'd509; + localparam RDY_THRESHOLD_LO = 9'd450; + localparam RDY_THRESHOLD_HI = 9'd500; + + // internal registers + + reg vdma_fs_toggle_m1 = 1'd0; + reg vdma_fs_toggle_m2 = 1'd0; + reg vdma_fs_toggle_m3 = 1'd0; + reg [22:0] vdma_tpm_data = 23'd0; + reg [ 8:0] vdma_raddr_g_m1 = 9'd0; + reg [ 8:0] vdma_raddr_g_m2 = 9'd0; + reg [ 8:0] vdma_raddr = 9'd0; + reg [ 8:0] vdma_addr_diff = 9'd0; + reg vdma_almost_full = 1'd0; + reg vdma_almost_empty = 1'd0; + reg hdmi_fs = 1'd0; + reg vdma_fs = 1'd0; + reg vdma_end_of_frame_d = 1'd0; + reg vdma_active_frame = 1'd0; + + // internal wires + + wire [47:0] vdma_tpm_data_s; + wire vdma_tpm_oos_s; + wire [ 9:0] vdma_addr_diff_s; + wire vdma_ovf_s; + wire vdma_unf_s; + + // grey to binary conversion + + function [8:0] g2b; + input [8:0] g; + reg [8:0] b; + begin + b[8] = g[8]; + b[7] = b[8] ^ g[7]; + b[6] = b[7] ^ g[6]; + b[5] = b[6] ^ g[5]; + b[4] = b[5] ^ g[4]; + b[3] = b[4] ^ g[3]; + b[2] = b[3] ^ g[2]; + b[1] = b[2] ^ g[1]; + b[0] = b[1] ^ g[0]; + g2b = b; + end + endfunction + + // hdmi frame sync + + always @(posedge vdma_clk or posedge vdma_rst) begin + if (vdma_rst == 1'b1) begin + vdma_fs_toggle_m1 <= 1'd0; + vdma_fs_toggle_m2 <= 1'd0; + vdma_fs_toggle_m3 <= 1'd0; + end else begin + vdma_fs_toggle_m1 <= hdmi_fs_toggle; + vdma_fs_toggle_m2 <= vdma_fs_toggle_m1; + vdma_fs_toggle_m3 <= vdma_fs_toggle_m2; + end + hdmi_fs <= vdma_fs_toggle_m2 ^ vdma_fs_toggle_m3; + end + + // dma frame sync + + always @(posedge vdma_clk or posedge vdma_rst) begin + if (vdma_rst == 1'b1) begin + vdma_end_of_frame_d <= 1'b0; + vdma_fs <= 1'b0; + end else begin + vdma_end_of_frame_d <= vdma_end_of_frame; + vdma_fs <= vdma_end_of_frame_d; + end + end + + // sync dma and hdmi frames + + always @(posedge vdma_clk) begin + if (vdma_rst == 1'b1) begin + vdma_fs_ret_toggle = 1'b0; + vdma_fs_waddr <= 9'b0; + end else begin + if (vdma_fs) begin + vdma_fs_ret_toggle <= ~vdma_fs_ret_toggle; + vdma_fs_waddr <= vdma_waddr ; + end + end + end + + // accept new frame from dma + + always @(posedge vdma_clk) begin + if (vdma_rst == 1'b1) begin + vdma_active_frame <= 1'b0; + end else begin + if ((vdma_active_frame == 1'b1) && (vdma_end_of_frame == 1'b1)) begin + vdma_active_frame <= 1'b0; + end else if ((vdma_active_frame == 1'b0) && (hdmi_fs == 1'b1)) begin + vdma_active_frame <= 1'b1; + end + end + end + + // vdma write + + always @(posedge vdma_clk) begin + vdma_wr <= vdma_valid & vdma_ready; + if (vdma_rst == 1'b1) begin + vdma_waddr <= 9'd0; + end else if (vdma_wr == 1'b1) begin + vdma_waddr <= vdma_waddr + 1'b1; + end + vdma_wdata <= {vdma_data[55:32], vdma_data[23:0]}; + end + + // test error conditions + + assign vdma_tpm_data_s = {vdma_tpm_data, 1'b1, vdma_tpm_data, 1'b0}; + assign vdma_tpm_oos_s = (vdma_wdata == vdma_tpm_data_s) ? 1'b0 : vdma_wr; + + always @(posedge vdma_clk) begin + if ((vdma_rst == 1'b1) || (vdma_fs == 1'b1)) begin + vdma_tpm_data <= 23'd0; + vdma_tpm_oos <= 1'd0; + end else if (vdma_wr == 1'b1) begin + vdma_tpm_data <= vdma_tpm_data + 1'b1; + vdma_tpm_oos <= vdma_tpm_oos_s; + end + end + + // overflow or underflow status + + assign vdma_addr_diff_s = {1'b1, vdma_waddr} - vdma_raddr; + assign vdma_ovf_s = (vdma_addr_diff < BUF_THRESHOLD_LO) ? vdma_almost_full : 1'b0; + assign vdma_unf_s = (vdma_addr_diff > BUF_THRESHOLD_HI) ? vdma_almost_empty : 1'b0; + + always @(posedge vdma_clk or posedge vdma_rst) begin + if (vdma_rst == 1'b1) begin + vdma_raddr_g_m1 <= 9'd0; + vdma_raddr_g_m2 <= 9'd0; + end else begin + vdma_raddr_g_m1 <= hdmi_raddr_g; + vdma_raddr_g_m2 <= vdma_raddr_g_m1; + end + end + + always @(posedge vdma_clk) begin + vdma_raddr <= g2b(vdma_raddr_g_m2); + vdma_addr_diff <= vdma_addr_diff_s[8:0]; + if (vdma_addr_diff >= RDY_THRESHOLD_HI) begin + vdma_ready <= 1'b0; + end else if (vdma_addr_diff <= RDY_THRESHOLD_LO) begin + vdma_ready <= vdma_active_frame; + end + if (vdma_addr_diff > BUF_THRESHOLD_HI) begin + vdma_almost_full <= 1'b1; + end else begin + vdma_almost_full <= 1'b0; + end + if (vdma_addr_diff < BUF_THRESHOLD_LO) begin + vdma_almost_empty <= 1'b1; + end else begin + vdma_almost_empty <= 1'b0; + end + vdma_ovf <= vdma_ovf_s; + vdma_unf <= vdma_unf_s; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/axi_spdif_tx/Makefile b/src/adi/hdl/library/axi_spdif_tx/Makefile new file mode 100644 index 00000000..469e8164 --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/Makefile @@ -0,0 +1,19 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_spdif_tx + +GENERIC_DEPS += ../common/axi_ctrlif.vhd +GENERIC_DEPS += ../common/axi_streaming_dma_tx_fifo.vhd +GENERIC_DEPS += ../common/dma_fifo.vhd +GENERIC_DEPS += ../common/pl330_dma_fifo.vhd +GENERIC_DEPS += axi_spdif_tx.vhd +GENERIC_DEPS += tx_encoder.vhd +GENERIC_DEPS += tx_package.vhd + +XILINX_DEPS += axi_spdif_tx_constr.xdc +XILINX_DEPS += axi_spdif_tx_ip.tcl + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx.vhd b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx.vhd new file mode 100644 index 00000000..6940c543 --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx.vhd @@ -0,0 +1,318 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.tx_package.all; +use work.axi_ctrlif; +use work.axi_streaming_dma_tx_fifo; +use work.pl330_dma_fifo; + +entity axi_spdif_tx is + generic ( + S_AXI_DATA_WIDTH : integer := 32; + S_AXI_ADDRESS_WIDTH : integer := 32; + DEVICE_FAMILY : string := "virtex6"; + DMA_TYPE : integer := 0 + ); + port ( + --SPDIF ports + spdif_data_clk : in std_logic; + spdif_tx_o : out std_logic; + + --AXI Lite interface + s_axi_aclk : in std_logic; + s_axi_aresetn : in std_logic; + s_axi_awaddr : in std_logic_vector(S_AXI_ADDRESS_WIDTH-1 downto 0); + s_axi_awprot : in std_logic_vector(2 downto 0); + s_axi_awvalid : in std_logic; + s_axi_wdata : in std_logic_vector(S_AXI_DATA_WIDTH-1 downto 0); + s_axi_wstrb : in std_logic_vector((S_AXI_DATA_WIDTH/8)-1 downto 0); + s_axi_wvalid : in std_logic; + s_axi_bready : in std_logic; + s_axi_araddr : in std_logic_vector(S_AXI_ADDRESS_WIDTH-1 downto 0); + s_axi_arprot : in std_logic_vector(2 downto 0); + s_axi_arvalid : in std_logic; + s_axi_rready : in std_logic; + s_axi_arready : out std_logic; + s_axi_rdata : out std_logic_vector(S_AXI_DATA_WIDTH-1 downto 0); + s_axi_rresp : out std_logic_vector(1 downto 0); + s_axi_rvalid : out std_logic; + s_axi_wready : out std_logic; + s_axi_bresp : out std_logic_vector(1 downto 0); + s_axi_bvalid : out std_logic; + s_axi_awready : out std_logic; + + --axi streaming interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(31 downto 0); + s_axis_tlast : in std_logic; + s_axis_tvalid : in std_logic; + + --PL330 DMA interface + dma_req_aclk : in std_logic; + dma_req_rstn : in std_logic; + dma_req_davalid : in std_logic; + dma_req_datype : in std_logic_vector(1 downto 0); + dma_req_daready : out std_logic; + dma_req_drvalid : out std_logic; + dma_req_drtype : out std_logic_vector(1 downto 0); + dma_req_drlast : out std_logic; + dma_req_drready : in std_logic + ); +end entity axi_spdif_tx; + +------------------------------------------------------------------------------ +-- Architecture section +------------------------------------------------------------------------------ + +architecture IMP of axi_spdif_tx is + ------------------------------------------ + -- SPDIF signals + ------------------------------------------ + signal config_reg : std_logic_vector(S_AXI_DATA_WIDTH-1 downto 0); + signal chstatus_reg : std_logic_vector(S_AXI_DATA_WIDTH-1 downto 0); + + signal chstat_freq : std_logic_vector(1 downto 0); + signal chstat_gstat, chstat_preem, chstat_copy, chstat_audio : std_logic; + signal sample_data_ack : std_logic; + signal sample_data: std_logic_vector(15 downto 0); + signal conf_mode : std_logic_vector(3 downto 0); + signal conf_ratio : std_logic_vector(7 downto 0); + signal conf_tinten, conf_txdata, conf_txen : std_logic; + signal channel : std_logic; + signal enable : boolean; + + signal fifo_data_out : std_logic_vector(31 downto 0); + signal fifo_data_ack : std_logic; + signal fifo_reset : std_logic; + signal tx_fifo_stb : std_logic; + + -- Register access + signal wr_data : std_logic_vector(31 downto 0); + signal rd_data : std_logic_vector(31 downto 0); + signal wr_addr : integer range 0 to 3; + signal rd_addr : integer range 0 to 3; + signal wr_stb : std_logic; + signal rd_ack : std_logic; +begin + + fifo_reset <= not conf_txdata; + enable <= conf_txdata = '1'; + fifo_data_ack <= channel and sample_data_ack; + + streaming_dma_gen: if DMA_TYPE = 0 generate + fifo: entity axi_streaming_dma_tx_fifo + generic map ( + RAM_ADDR_WIDTH => 3, + FIFO_DWIDTH => 32 + ) + port map ( + clk => s_axi_aclk, + resetn => s_axi_aresetn, + fifo_reset => fifo_reset, + enable => enable, + s_axis_aclk => s_axis_aclk, + s_axis_tready => s_axis_tready, + s_axis_tdata => s_axis_tdata, + s_axis_tvalid => s_axis_tlast, + s_axis_tlast => s_axis_tvalid, + + out_ack => fifo_data_ack, + out_data => fifo_data_out + ); + end generate; + + no_streaming_dma_gen: if DMA_TYPE /= 0 generate + s_axis_tready <= '0'; + end generate; + + pl330_dma_gen: if DMA_TYPE = 1 generate + tx_fifo_stb <= '1' when wr_addr = 3 and wr_stb = '1' else '0'; + + fifo: entity pl330_dma_fifo + generic map( + RAM_ADDR_WIDTH => 3, + FIFO_DWIDTH => 32, + FIFO_DIRECTION => 0 + ) + port map ( + clk => s_axi_aclk, + resetn => s_axi_aresetn, + fifo_reset => fifo_reset, + enable => enable, + + in_data => wr_data, + in_stb => tx_fifo_stb, + + out_ack => fifo_data_ack, + out_data => fifo_data_out, + + dclk => dma_req_aclk, + dresetn => dma_req_rstn, + davalid => dma_req_davalid, + daready => dma_req_daready, + datype => dma_req_datype, + drvalid => dma_req_drvalid, + drready => dma_req_drreadY, + drtype => dma_req_drtype, + drlast => dma_req_drlast + ); + end generate; + + no_pl330_dma_gen: if DMA_TYPE /= 1 generate + dma_req_daready <= '0'; + dma_req_drvalid <= '0'; + dma_req_drtype <= (others => '0'); + dma_req_drlast <= '0'; + end generate; + + sample_data_mux: process (fifo_data_out, channel) is + begin + if channel = '0' then + sample_data <= fifo_data_out(15 downto 0); + else + sample_data <= fifo_data_out(31 downto 16); + end if; + end process; + + -- Configuration signals update + conf_mode(3 downto 0) <= config_reg(23 downto 20); + conf_ratio(7 downto 0) <= config_reg(15 downto 8); + conf_tinten <= config_reg(2); + conf_txdata <= config_reg(1); + conf_txen <= config_reg(0); + + -- Channel status signals update + chstat_freq(1 downto 0) <= chstatus_reg(7 downto 6); + chstat_gstat <= chstatus_reg(3); + chstat_preem <= chstatus_reg(2); + chstat_copy <= chstatus_reg(1); + chstat_audio <= chstatus_reg(0); + + -- Transmit encoder + TENC: tx_encoder + generic map ( + DATA_WIDTH => 16 + ) + port map ( + up_clk => s_axi_aclk, + data_clk => spdif_data_clk, -- data clock + resetn => s_axi_aresetn, -- resetn + conf_mode => conf_mode, -- sample format + conf_ratio => conf_ratio, -- clock divider + conf_txdata => conf_txdata, -- sample data enable + conf_txen => conf_txen, -- spdif signal enable + chstat_freq => chstat_freq, -- sample freq. + chstat_gstat => chstat_gstat, -- generation status + chstat_preem => chstat_preem, -- preemphasis status + chstat_copy => chstat_copy, -- copyright bit + chstat_audio => chstat_audio, -- data format + sample_data => sample_data, -- audio data + sample_data_ack => sample_data_ack, -- sample buffer read + channel => channel, -- which channel should be read + spdif_tx_o => spdif_tx_o -- SPDIF output signal + ); + + ctrlif: entity axi_ctrlif + generic map ( + C_S_AXI_ADDR_WIDTH => S_AXI_ADDRESS_WIDTH, + C_S_AXI_DATA_WIDTH => S_AXI_DATA_WIDTH, + C_NUM_REG => 4 + ) + port map( + s_axi_aclk => s_axi_aclk, + s_axi_aresetn => s_axi_aresetn, + s_axi_awaddr => s_axi_awaddr, + s_axi_awvalid => s_axi_awvalid, + s_axi_wdata => s_axi_wdata, + s_axi_wstrb => s_axi_wstrb, + s_axi_wvalid => s_axi_wvalid, + s_axi_bready => s_axi_bready, + s_axi_araddr => s_axi_araddr, + s_axi_arvalid => s_axi_arvalid, + s_axi_rready => s_axi_rready, + s_axi_arready => s_axi_arready, + s_axi_rdata => s_axi_rdata, + s_axi_rresp => s_axi_rresp, + s_axi_rvalid => s_axi_rvalid, + s_axi_wready => s_axi_wready, + s_axi_bresp => s_axi_bresp, + s_axi_bvalid => s_axi_bvalid, + s_axi_awready => s_axi_awready, + + rd_addr => rd_addr, + rd_data => rd_data, + rd_ack => rd_ack, + rd_stb => '1', + + wr_addr => wr_addr, + wr_data => wr_data, + wr_ack => '1', + wr_stb => wr_stb + ); + + process (s_axi_aclk) + begin + if rising_edge(s_axi_aclk) then + if s_axi_aresetn = '0' then + config_reg <= (others => '0'); + chstatus_reg <= (others => '0'); + else + if wr_stb = '1' then + case wr_addr is + when 0 => config_reg <= wr_data; + when 1 => chstatus_reg <= wr_data; + when others => null; + end case; + end if; + end if; + end if; + end process; + + process (rd_addr, config_reg, chstatus_reg) + begin + case rd_addr is + when 0 => rd_data <= config_reg; + when 1 => rd_data <= chstatus_reg; + when others => rd_data <= (others => '0'); + end case; + end process; + +end IMP; diff --git a/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_constr.xdc b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_constr.xdc new file mode 100644 index 00000000..c874131d --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_constr.xdc @@ -0,0 +1,11 @@ +set_property ASYNC_REG TRUE \ + [get_cells -hier cdc_sync_stage1_*_reg] \ + [get_cells -hier cdc_sync_stage2_*_reg] + +set_false_path \ + -from [get_cells -hier cdc_sync_stage0_*_reg -filter {PRIMITIVE_SUBGROUP == flop || primitive_subgroup == SDR}] \ + -to [get_cells -hier cdc_sync_stage1_*_reg -filter {PRIMITIVE_SUBGROUP == flop || primitive_subgroup == SDR}] + +set_false_path \ + -from [get_cells -hier spdif_out_reg -filter {PRIMITIVE_SUBGROUP == flop || primitive_subgroup == SDR}] \ + -to [get_cells -hier spdif_tx_o_reg -filter {PRIMITIVE_SUBGROUP == flop || primitive_subgroup == SDR}] diff --git a/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_ip.tcl b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_ip.tcl new file mode 100644 index 00000000..7919a6f0 --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/axi_spdif_tx_ip.tcl @@ -0,0 +1,50 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_spdif_tx +adi_ip_files axi_spdif_tx [list \ + "$ad_hdl_dir/library/common/axi_ctrlif.vhd" \ + "$ad_hdl_dir/library/common/axi_streaming_dma_tx_fifo.vhd" \ + "$ad_hdl_dir/library/common/pl330_dma_fifo.vhd" \ + "$ad_hdl_dir/library/common/dma_fifo.vhd" \ + "tx_package.vhd" \ + "tx_encoder.vhd" \ + "axi_spdif_tx.vhd" \ + "axi_spdif_tx_constr.xdc" ] + +adi_ip_properties axi_spdif_tx +adi_ip_infer_streaming_interfaces axi_spdif_tx + +adi_add_bus "dma_ack" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"dma_req_davalid" "TVALID"} \ + {"dma_req_daready" "TREADY"} \ + {"dma_req_datype" "TUSER"} ] +adi_add_bus "dma_req" "master" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"dma_req_drvalid" "TVALID"} \ + {"dma_req_drready" "TREADY"} \ + {"dma_req_drtype" "TUSER"} \ + {"dma_req_drlast" "TLAST"} ] + +# Clock and reset are for both dma_req and dma_ack +adi_add_bus_clock "dma_req_aclk" "dma_req:dma_ack" "dma_req_rstn" + +adi_set_bus_dependency "s_axis" "s_axis" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE')) = 0)" + +adi_set_bus_dependency "dma_ack" "dma_req_da" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE')) = 1)" +adi_set_bus_dependency "dma_req" "dma_req_dr" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE')) = 1)" +adi_set_ports_dependency "dma_req_aclk" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE')) = 1)" +adi_set_ports_dependency "dma_req_rstn" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE')) = 1)" + +ipx::save_core [ipx::current_core] + diff --git a/src/adi/hdl/library/axi_spdif_tx/tx_encoder.vhd b/src/adi/hdl/library/axi_spdif_tx/tx_encoder.vhd new file mode 100644 index 00000000..898f81ee --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/tx_encoder.vhd @@ -0,0 +1,495 @@ +---------------------------------------------------------------------- +---- ---- +---- WISHBONE SPDIF IP Core ---- +---- ---- +---- This file is part of the SPDIF project ---- +---- http://www.opencores.org/cores/spdif_interface/ ---- +---- ---- +---- Description ---- +---- SPDIF transmitter signal encoder. Reads out samples from the ---- +---- sample buffer, assembles frames and subframes and encodes ---- +---- serial data as bi-phase mark code. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author(s): ---- +---- - Geir Drange, gedra@opencores.org ---- +---- ---- +---------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2004 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: not supported by cvs2svn $ +-- +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity tx_encoder is + generic (DATA_WIDTH: integer range 16 to 32 := 32); + port ( + up_clk: in std_logic; -- clock + data_clk : in std_logic; -- data clock + resetn : in std_logic; -- resetn + conf_mode: in std_logic_vector(3 downto 0); -- sample format + conf_ratio: in std_logic_vector(7 downto 0); -- clock divider + conf_txdata: in std_logic; -- sample data enable + conf_txen: in std_logic; -- spdif signal enable + chstat_freq: in std_logic_vector(1 downto 0); -- sample freq. + chstat_gstat: in std_logic; -- generation status + chstat_preem: in std_logic; -- preemphasis status + chstat_copy: in std_logic; -- copyright bit + chstat_audio: in std_logic; -- data format + sample_data: in std_logic_vector(DATA_WIDTH - 1 downto 0); -- audio data + sample_data_ack: out std_logic; -- sample buffer read + channel: out std_logic; + spdif_tx_o: out std_logic); +end tx_encoder; + +architecture rtl of tx_encoder is + + signal spdif_clk_en, spdif_out : std_logic; + signal clk_cnt : integer range 0 to 511; + type buf_states is (IDLE, READ_CHA, READ_CHB, CHA_RDY, CHB_RDY); + signal bufctrl : buf_states; + signal cha_samp_ack, chb_samp_ack : std_logic; + type frame_states is (IDLE, BLOCK_START, CHANNEL_A, CHANNEL_B); + signal framest : frame_states; + signal frame_cnt : integer range 0 to 191; + signal bit_cnt, par_cnt : integer range 0 to 31; + signal inv_preamble, toggle, valid : std_logic; + signal def_user_data, def_ch_status : std_logic_vector(191 downto 0); + signal active_user_data, active_ch_status : std_logic_vector(191 downto 0); + signal audio : std_logic_vector(23 downto 0); + signal par_vector : std_logic_vector(26 downto 0); + signal send_audio : std_logic; + + signal cdc_sync_stage0_tick_counter : std_logic := '0'; + signal cdc_sync_stage1_tick_counter : std_logic := '0'; + signal cdc_sync_stage2_tick_counter : std_logic := '0'; + signal cdc_sync_stage3_tick_counter : std_logic := '0'; + signal tick_counter : std_logic; + + constant X_PREAMBLE : std_logic_vector(0 to 7) := "11100010"; + constant Y_PREAMBLE : std_logic_vector(0 to 7) := "11100100"; + constant Z_PREAMBLE : std_logic_vector(0 to 7) := "11101000"; + + function encode_bit ( + signal bit_cnt : integer; -- sub-frame bit position + signal valid : std_logic; -- validity bit + signal frame_cnt : integer; -- frame counter + signal par_cnt : integer; -- parity counter + signal user_data : std_logic_vector(191 downto 0); + signal ch_status : std_logic_vector(191 downto 0); + signal audio : std_logic_vector(23 downto 0); + signal toggle : std_logic; + signal prev_spdif : std_logic) -- prev. value of spdif signal + + return std_logic is + variable spdif, next_bit : std_logic; + begin + if bit_cnt > 3 and bit_cnt < 28 then -- audio part + next_bit := audio(bit_cnt - 4); + elsif bit_cnt = 28 then -- validity bit + next_bit := valid; + elsif bit_cnt = 29 then -- user data + next_bit := user_data(frame_cnt); + elsif bit_cnt = 30 then + next_bit := ch_status(frame_cnt); -- channel status + elsif bit_cnt = 31 then + if par_cnt mod 2 = 1 then + next_bit := '1'; + else + next_bit := '0'; + end if; + end if; + -- bi-phase mark encoding: + if next_bit = '0' then + if toggle = '0' then + spdif := not prev_spdif; + else + spdif := prev_spdif; + end if; + else + spdif := not prev_spdif; + end if; + return(spdif); + end encode_bit; + +begin + +-- SPDIF clock enable generation. The clock is a fraction of the data clock, +-- determined by the conf_ratio value. + DCLK : process (data_clk) + begin + if rising_edge(data_clk) then + cdc_sync_stage0_tick_counter <= not cdc_sync_stage0_tick_counter; + end if; + end process DCLK; + + process (up_clk) begin + if rising_edge(up_clk) then + cdc_sync_stage1_tick_counter <= cdc_sync_stage0_tick_counter; + cdc_sync_stage2_tick_counter <= cdc_sync_stage1_tick_counter; + cdc_sync_stage3_tick_counter <= cdc_sync_stage2_tick_counter; + end if; + end process; + + tick_counter <= cdc_sync_stage3_tick_counter xor cdc_sync_stage2_tick_counter; + + CGEN: process (up_clk) + begin + if rising_edge(up_clk) then + if resetn = '0' or conf_txen = '0' then + clk_cnt <= 0; + spdif_clk_en <= '0'; + else + spdif_clk_en <= '0'; + + if tick_counter = '1' then + if clk_cnt < to_integer(unsigned(conf_ratio)) then + clk_cnt <= clk_cnt + 1; + else + clk_cnt <= 0; + spdif_clk_en <= '1'; + end if; + end if; + end if; + end if; + end process CGEN; + + SRD: process (up_clk) + begin + if rising_edge(up_clk) then + if resetn = '0' or conf_txdata = '0' then + bufctrl <= IDLE; + sample_data_ack <= '0'; + channel <= '0'; + else + case bufctrl is + when IDLE => + sample_data_ack <= '0'; + if conf_txdata = '1' then + bufctrl <= READ_CHA; + sample_data_ack <='1'; + end if; + when READ_CHA => + channel <= '0'; + sample_data_ack <= '0'; + bufctrl <= CHA_RDY; + when CHA_RDY => + if cha_samp_ack = '1' then + sample_data_ack <= '1'; + bufctrl <= READ_CHB; + end if; + when READ_CHB => + channel <= '1'; + sample_data_ack <= '0'; + bufctrl <= CHB_RDY; + when CHB_RDY => + if chb_samp_ack = '1' then + sample_data_ack <= '1'; + bufctrl <= READ_CHA; + end if; + when others => + bufctrl <= IDLE; + end case; + end if; + end if; + end process SRD; + + TXSYNC: process (data_clk) + begin + if (rising_edge(data_clk)) then + spdif_tx_o <= spdif_out; + end if; + end process TXSYNC; + +-- State machine that generates sub-frames and blocks + + FRST: process (up_clk) + begin + if rising_edge(up_clk) then + if resetn = '0' or conf_txen = '0' then + framest <= IDLE; + frame_cnt <= 0; + bit_cnt <= 0; + spdif_out <= '0'; + inv_preamble <= '0'; + toggle <= '0'; + valid <= '1'; + send_audio <= '0'; + cha_samp_ack <= '0'; + chb_samp_ack <= '0'; + else + if spdif_clk_en = '1' then -- SPDIF clock is twice the bit rate + case framest is + when IDLE => + bit_cnt <= 0; + frame_cnt <= 0; + inv_preamble <= '0'; + toggle <= '0'; + framest <= BLOCK_START; + when BLOCK_START => -- Start of channels status block/Ch. A + chb_samp_ack <= '0'; + toggle <= not toggle; -- Each bit uses two clock enables, + if toggle = '1' then -- counted by the toggle bit. + if bit_cnt < 31 then + bit_cnt <= bit_cnt + 1; + else + bit_cnt <= 0; + if send_audio = '1' then + cha_samp_ack <= '1'; + end if; + framest <= CHANNEL_B; + end if; + end if; + -- Block start uses preamble Z. + if bit_cnt < 4 then + if toggle = '0' then + spdif_out <= Z_PREAMBLE(2 * bit_cnt) xor inv_preamble; + else + spdif_out <= Z_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble; + end if; + par_cnt <= 0; + elsif bit_cnt > 3 and bit_cnt <= 31 then + spdif_out <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + if bit_cnt = 31 then + inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + end if; + if toggle = '0' then + if bit_cnt > 3 and bit_cnt < 31 and + par_vector(bit_cnt - 4) = '1' then + par_cnt <= par_cnt + 1; + end if; + end if; + end if; + when CHANNEL_A => -- Sub-frame: channel A. + chb_samp_ack <= '0'; + toggle <= not toggle; + if toggle = '1' then + if bit_cnt < 31 then + bit_cnt <= bit_cnt + 1; + else + bit_cnt <= 0; + if spdif_out = '1' then + inv_preamble <= '1'; + else + inv_preamble <= '0'; + end if; + if send_audio = '1' then + cha_samp_ack <= '1'; + end if; + framest <= CHANNEL_B; + end if; + end if; + -- Channel A uses preable X. + if bit_cnt < 4 then + if toggle = '0' then + spdif_out <= X_PREAMBLE(2 * bit_cnt) xor inv_preamble; + else + spdif_out <= X_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble; + end if; + par_cnt <= 0; + elsif bit_cnt > 3 and bit_cnt <= 31 then + spdif_out <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + if bit_cnt = 31 then + inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + end if; + if toggle = '0' then + if bit_cnt > 3 and bit_cnt < 31 and + par_vector(bit_cnt - 4) = '1' then + par_cnt <= par_cnt + 1; + end if; + end if; + end if; + when CHANNEL_B => -- Sub-frame: channel B. + cha_samp_ack <= '0'; + toggle <= not toggle; + if toggle = '1' then + if bit_cnt < 31 then + bit_cnt <= bit_cnt + 1; + else + bit_cnt <= 0; + valid <= not conf_txdata; + if spdif_out = '1' then + inv_preamble <= '1'; + else + inv_preamble <= '0'; + end if; + send_audio <= conf_txdata; -- 1 if audio samples sohuld be sent + if send_audio = '1' then + chb_samp_ack <= '1'; + end if; + if frame_cnt < 191 then -- One block is 192 frames + frame_cnt <= frame_cnt + 1; + framest <= CHANNEL_A; + else + frame_cnt <= 0; + framest <= BLOCK_START; + end if; + end if; + end if; + -- Channel B uses preable Y. + if bit_cnt < 4 then + if toggle = '0' then + spdif_out <= Y_PREAMBLE(2 * bit_cnt) xor inv_preamble; + else + spdif_out <= Y_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble; + end if; + par_cnt <= 0; + elsif bit_cnt > 3 and bit_cnt <= 31 then + spdif_out <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + if bit_cnt = 31 then + inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt, + par_cnt, active_user_data, + active_ch_status, + audio, toggle, spdif_out); + end if; + if toggle = '0' then + if bit_cnt > 3 and bit_cnt < 31 and + par_vector(bit_cnt - 4) = '1' then + par_cnt <= par_cnt + 1; + end if; + end if; + end if; + when others => + framest <= IDLE; + end case; + end if; + end if; + end if; + end process FRST; + +-- Audio data latching + DA32: if DATA_WIDTH = 32 generate + ALAT: process (up_clk) + begin + if rising_edge(up_clk) then + if send_audio = '0' then + audio(23 downto 0) <= (others => '0'); + else + case to_integer(unsigned(conf_mode)) is + when 0 => -- 16 bit audio + audio(23 downto 8) <= sample_data(15 downto 0); + audio(7 downto 0) <= (others => '0'); + when 1 => -- 17 bit audio + audio(23 downto 7) <= sample_data(16 downto 0); + audio(6 downto 0) <= (others => '0'); + when 2 => -- 18 bit audio + audio(23 downto 6) <= sample_data(17 downto 0); + audio(5 downto 0) <= (others => '0'); + when 3 => -- 19 bit audio + audio(23 downto 5) <= sample_data(18 downto 0); + audio(4 downto 0) <= (others => '0'); + when 4 => -- 20 bit audio + audio(23 downto 4) <= sample_data(19 downto 0); + audio(3 downto 0) <= (others => '0'); + when 5 => -- 21 bit audio + audio(23 downto 3) <= sample_data(20 downto 0); + audio(2 downto 0) <= (others => '0'); + when 6 => -- 22 bit audio + audio(23 downto 2) <= sample_data(21 downto 0); + audio(1 downto 0) <= (others => '0'); + when 7 => -- 23 bit audio + audio(23 downto 1) <= sample_data(22 downto 0); + audio(0) <= '0'; + when 8 => -- 24 bit audio + audio(23 downto 0) <= sample_data(23 downto 0); + when others => -- unsupported modes + audio(23 downto 0) <= (others => '0'); + end case; + end if; + end if; + end process ALAT; + end generate DA32; + + DA16: if DATA_WIDTH = 16 generate + ALAT: process (up_clk) + begin + if rising_edge(up_clk) then + if send_audio = '0' then + audio(23 downto 0) <= (others => '0'); + else + audio(23 downto 8) <= sample_data(15 downto 0); + audio(7 downto 0) <= (others => '0'); + end if; + end if; + end process ALAT; + end generate DA16; + +-- Parity vector. These bits are counted to generate even parity + par_vector(23 downto 0) <= audio(23 downto 0); + par_vector(24) <= valid; + par_vector(25) <= active_user_data(frame_cnt); + par_vector(26) <= active_ch_status(frame_cnt); + +-- Channel status and user datat to be used if buffers are disabled. +-- User data is then all zero, while channel status bits are taken from +-- register TxChStat. + def_user_data(191 downto 0) <= (others => '0'); + def_ch_status(0) <= '0'; -- consumer mode + def_ch_status(1) <= chstat_audio; -- audio bit + def_ch_status(2) <= chstat_copy; -- copy right + def_ch_status(5 downto 3) <= "000" when chstat_preem = '0' + else "001"; -- pre-emphasis + def_ch_status(7 downto 6) <= "00"; + def_ch_status(14 downto 8) <= (others => '0'); + def_ch_status(15) <= chstat_gstat; -- generation status + def_ch_status(23 downto 16) <= (others => '0'); + def_ch_status(27 downto 24) <= "0000" when chstat_freq = "00" else + "0010" when chstat_freq = "01" else + "0011" when chstat_freq = "10" else + "0001"; + def_ch_status(191 downto 28) <= (others => '0'); --191 28 + +-- Generate channel status vector based on configuration register setting. + active_ch_status <= def_ch_status; + +-- Generate user data vector based on configuration register setting. + active_user_data <= def_user_data; + +end rtl; diff --git a/src/adi/hdl/library/axi_spdif_tx/tx_package.vhd b/src/adi/hdl/library/axi_spdif_tx/tx_package.vhd new file mode 100644 index 00000000..2e658590 --- /dev/null +++ b/src/adi/hdl/library/axi_spdif_tx/tx_package.vhd @@ -0,0 +1,88 @@ +---------------------------------------------------------------------- +---- ---- +---- WISHBONE SPDIF IP Core ---- +---- ---- +---- This file is part of the SPDIF project ---- +---- http://www.opencores.org/cores/spdif_interface/ ---- +---- ---- +---- Description ---- +---- SPDIF transmitter component package. ---- +---- ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author(s): ---- +---- - Geir Drange, gedra@opencores.org ---- +---- ---- +---------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2004 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: not supported by cvs2svn $ +-- Revision 1.2 2004/07/14 17:58:49 gedra +-- Added new components. +-- +-- Revision 1.1 2004/07/13 18:30:25 gedra +-- Transmitter component declarations. +-- +-- +-- + +library ieee; +use ieee.std_logic_1164.all; + +package tx_package is + + component tx_encoder + generic + ( + DATA_WIDTH: integer range 16 to 32 := 32 + ); + port + ( + up_clk: in std_logic; -- clock + data_clk : in std_logic; -- data clock + resetn : in std_logic; -- resetn + conf_mode: in std_logic_vector(3 downto 0); -- sample format + conf_ratio: in std_logic_vector(7 downto 0); -- clock divider + conf_txdata: in std_logic; -- sample data enable + conf_txen: in std_logic; -- spdif signal enable + chstat_freq: in std_logic_vector(1 downto 0); -- sample freq. + chstat_gstat: in std_logic; -- generation status + chstat_preem: in std_logic; -- preemphasis status + chstat_copy: in std_logic; -- copyright bit + chstat_audio: in std_logic; -- data format + sample_data: in std_logic_vector(DATA_WIDTH - 1 downto 0); -- audio data + sample_data_ack : out std_logic; -- sample buffer read + channel: out std_logic; + spdif_tx_o: out std_logic + ); + end component; + +end tx_package; diff --git a/src/adi/hdl/library/common/ad_addsub.v b/src/adi/hdl/library/common/ad_addsub.v new file mode 100644 index 00000000..250f4576 --- /dev/null +++ b/src/adi/hdl/library/common/ad_addsub.v @@ -0,0 +1,115 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +// A simple adder/substracter width preconfigured input ports width and turn-around value +// Output = A - B_constant or A + B_constant +// Constraints: Awidth >= Bwidth + +`timescale 1ns/1ps + +module ad_addsub #( + + parameter A_DATA_WIDTH = 32, + parameter B_DATA_VALUE = 32'h1, + parameter ADD_OR_SUB_N = 0) ( + input clk, + input [(A_DATA_WIDTH-1):0] A, + input [(A_DATA_WIDTH-1):0] Amax, + output reg [(A_DATA_WIDTH-1):0] out, + input CE); + + + localparam ADDER = 1; + localparam SUBSTRACTER = 0; + + // registers + + reg [A_DATA_WIDTH:0] out_d = 'b0; + reg [A_DATA_WIDTH:0] out_d2 = 'b0; + reg [(A_DATA_WIDTH-1):0] A_d = 'b0; + reg [(A_DATA_WIDTH-1):0] Amax_d = 'b0; + reg [(A_DATA_WIDTH-1):0] Amax_d2 = 'b0; + + // constant regs + + reg [(A_DATA_WIDTH-1):0] B_reg = B_DATA_VALUE; + + // latch the inputs + + always @(posedge clk) begin + A_d <= A; + Amax_d <= Amax; + Amax_d2 <= Amax_d; + end + + // ADDER/SUBSTRACTER + + always @(posedge clk) begin + if ( ADD_OR_SUB_N == ADDER ) begin + out_d <= A_d + B_reg; + end else begin + out_d <= A_d - B_reg; + end + end + + // Resolve + + always @(posedge clk) begin + if ( ADD_OR_SUB_N == ADDER ) begin + if ( out_d > Amax_d2 ) begin + out_d2 <= out_d - Amax_d2; + end else begin + out_d2 <= out_d; + end + end else begin // SUBSTRACTER + if ( out_d[A_DATA_WIDTH] == 1'b1 ) begin + out_d2 <= Amax_d2 + out_d; + end else begin + out_d2 <= out_d; + end + end + end + + // output logic + + always @(posedge clk) begin + if ( CE ) begin + out <= out_d2; + end else begin + out <= 'b0; + end + end + +endmodule diff --git a/src/adi/hdl/library/common/ad_adl5904_rst.v b/src/adi/hdl/library/common/ad_adl5904_rst.v new file mode 100644 index 00000000..ce5f7aa2 --- /dev/null +++ b/src/adi/hdl/library/common/ad_adl5904_rst.v @@ -0,0 +1,78 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_adl5904_rst ( + + input sys_cpu_clk, + input rf_peak_det_n, + output rf_peak_rst); + + // internal registers + + reg rf_peak_det_n_d = 'd0; + reg rf_peak_det_enb_d = 'd0; + reg rf_peak_rst_enb = 'd0; + reg rf_peak_rst_int = 'd0; + + // internal signals + + wire rf_peak_det_enb_s; + wire rf_peak_rst_1_s; + wire rf_peak_rst_0_s; + + // adl5904 input protection + + assign rf_peak_rst = rf_peak_rst_int; + assign rf_peak_det_enb_s = ~(rf_peak_det_n_d & rf_peak_det_n); + assign rf_peak_rst_1_s = ~rf_peak_det_enb_d & rf_peak_det_enb_s; + assign rf_peak_rst_0_s = rf_peak_det_enb_d & ~rf_peak_det_enb_s; + + always @(posedge sys_cpu_clk) begin + rf_peak_det_n_d <= rf_peak_det_n; + rf_peak_det_enb_d <= rf_peak_det_enb_s; + if (rf_peak_rst_1_s == 1'b1) begin + rf_peak_rst_enb <= 1'b1; + end else if (rf_peak_rst_0_s == 1'b1) begin + rf_peak_rst_enb <= 1'b0; + end + rf_peak_rst_int = ~rf_peak_rst_int & rf_peak_rst_enb; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_axis_inf_rx.v b/src/adi/hdl/library/common/ad_axis_inf_rx.v new file mode 100644 index 00000000..0b49eb0d --- /dev/null +++ b/src/adi/hdl/library/common/ad_axis_inf_rx.v @@ -0,0 +1,193 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_axis_inf_rx #( + + parameter DATA_WIDTH = 16) ( + + // adi interface + + input clk, + input rst, + input valid, + input last, + input [(DATA_WIDTH-1):0] data, + + // xilinx interface + + output reg inf_valid, + output reg inf_last, + output reg [(DATA_WIDTH-1):0] inf_data, + input inf_ready); + + // internal registers + + reg [ 2:0] wcnt = 'd0; + reg wlast_0 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_0 = 'd0; + reg wlast_1 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_1 = 'd0; + reg wlast_2 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_2 = 'd0; + reg wlast_3 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_3 = 'd0; + reg wlast_4 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_4 = 'd0; + reg wlast_5 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_5 = 'd0; + reg wlast_6 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_6 = 'd0; + reg wlast_7 = 'd0; + reg [(DATA_WIDTH-1):0] wdata_7 = 'd0; + reg [ 2:0] rcnt = 'd0; + + // internal signals + + wire inf_ready_s; + reg inf_last_s; + reg [(DATA_WIDTH-1):0] inf_data_s; + + // write interface + + always @(posedge clk) begin + if (rst == 1'b1) begin + wcnt <= 'd0; + end else if (valid == 1'b1) begin + wcnt <= wcnt + 1'b1; + end + if ((wcnt == 3'd0) && (valid == 1'b1)) begin + wlast_0 <= last; + wdata_0 <= data; + end + if ((wcnt == 3'd1) && (valid == 1'b1)) begin + wlast_1 <= last; + wdata_1 <= data; + end + if ((wcnt == 3'd2) && (valid == 1'b1)) begin + wlast_2 <= last; + wdata_2 <= data; + end + if ((wcnt == 3'd3) && (valid == 1'b1)) begin + wlast_3 <= last; + wdata_3 <= data; + end + if ((wcnt == 3'd4) && (valid == 1'b1)) begin + wlast_4 <= last; + wdata_4 <= data; + end + if ((wcnt == 3'd5) && (valid == 1'b1)) begin + wlast_5 <= last; + wdata_5 <= data; + end + if ((wcnt == 3'd6) && (valid == 1'b1)) begin + wlast_6 <= last; + wdata_6 <= data; + end + if ((wcnt == 3'd7) && (valid == 1'b1)) begin + wlast_7 <= last; + wdata_7 <= data; + end + end + + // read interface + + assign inf_ready_s = inf_ready | ~inf_valid; + + always @(rcnt or wlast_0 or wdata_0 or wlast_1 or wdata_1 or + wlast_2 or wdata_2 or wlast_3 or wdata_3 or wlast_4 or wdata_4 or + wlast_5 or wdata_5 or wlast_6 or wdata_6 or wlast_7 or wdata_7) begin + case (rcnt) + 3'd0: begin + inf_last_s = wlast_0; + inf_data_s = wdata_0; + end + 3'd1: begin + inf_last_s = wlast_1; + inf_data_s = wdata_1; + end + 3'd2: begin + inf_last_s = wlast_2; + inf_data_s = wdata_2; + end + 3'd3: begin + inf_last_s = wlast_3; + inf_data_s = wdata_3; + end + 3'd4: begin + inf_last_s = wlast_4; + inf_data_s = wdata_4; + end + 3'd5: begin + inf_last_s = wlast_5; + inf_data_s = wdata_5; + end + 3'd6: begin + inf_last_s = wlast_6; + inf_data_s = wdata_6; + end + default: begin + inf_last_s = wlast_7; + inf_data_s = wdata_7; + end + endcase + end + + always @(posedge clk) begin + if (rst == 1'b1) begin + rcnt <= 'd0; + inf_valid <= 'd0; + inf_last <= 'b0; + inf_data <= 'd0; + end else if (inf_ready_s == 1'b1) begin + if (rcnt == wcnt) begin + rcnt <= rcnt; + inf_valid <= 1'd0; + inf_last <= 1'b0; + inf_data <= 'd0; + end else begin + rcnt <= rcnt + 1'b1; + inf_valid <= 1'b1; + inf_last <= inf_last_s; + inf_data <= inf_data_s; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_b2g.v b/src/adi/hdl/library/common/ad_b2g.v new file mode 100644 index 00000000..15f68c0f --- /dev/null +++ b/src/adi/hdl/library/common/ad_b2g.v @@ -0,0 +1,59 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_b2g #( + + parameter DATA_WIDTH = 8) ( + + input [DATA_WIDTH-1:0] din, + output [DATA_WIDTH-1:0] dout); + + function [DATA_WIDTH-1:0] b2g; + input [DATA_WIDTH-1:0] b; + integer i; + begin + b2g[DATA_WIDTH-1] = b[DATA_WIDTH-1]; + for (i = DATA_WIDTH-1; i > 0; i = i -1) begin + b2g[i-1] = b[i] ^ b[i-1]; + end + end + endfunction + + assign dout = b2g(din); + +endmodule + diff --git a/src/adi/hdl/library/common/ad_csc_1.v b/src/adi/hdl/library/common/ad_csc_1.v new file mode 100644 index 00000000..3cacf023 --- /dev/null +++ b/src/adi/hdl/library/common/ad_csc_1.v @@ -0,0 +1,115 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// csc = c1*d[23:16] + c2*d[15:8] + c3*d[7:0] + c4; + +`timescale 1ns/100ps + +module ad_csc_1 #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // data + + input clk, + input [DW:0] sync, + input [23:0] data, + + // constants + + input [16:0] C1, + input [16:0] C2, + input [16:0] C3, + input [24:0] C4, + + // sync is delay matched + + output [DW:0] csc_sync_1, + output [ 7:0] csc_data_1); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // internal wires + + wire [24:0] data_1_m_s; + wire [24:0] data_2_m_s; + wire [24:0] data_3_m_s; + wire [DW:0] sync_3_m_s; + + // c1*R + + ad_csc_1_mul #(.DELAY_DATA_WIDTH(1)) i_mul_c1 ( + .clk (clk), + .data_a (C1), + .data_b (data[23:16]), + .data_p (data_1_m_s), + .ddata_in (1'd0), + .ddata_out ()); + + // c2*G + + ad_csc_1_mul #(.DELAY_DATA_WIDTH(1)) i_mul_c2 ( + .clk (clk), + .data_a (C2), + .data_b (data[15:8]), + .data_p (data_2_m_s), + .ddata_in (1'd0), + .ddata_out ()); + + // c3*B + + ad_csc_1_mul #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH)) i_mul_c3 ( + .clk (clk), + .data_a (C3), + .data_b (data[7:0]), + .data_p (data_3_m_s), + .ddata_in (sync), + .ddata_out (sync_3_m_s)); + + // sum + c4 + + ad_csc_1_add #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH)) i_add_c4 ( + .clk (clk), + .data_1 (data_1_m_s), + .data_2 (data_2_m_s), + .data_3 (data_3_m_s), + .data_4 (C4), + .data_p (csc_data_1), + .ddata_in (sync_3_m_s), + .ddata_out (csc_sync_1)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_csc_1_add.v b/src/adi/hdl/library/common/ad_csc_1_add.v new file mode 100644 index 00000000..3acb3970 --- /dev/null +++ b/src/adi/hdl/library/common/ad_csc_1_add.v @@ -0,0 +1,147 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Color Space Conversion, adder. This is a simple adder, but had to be +// pipe-lined for faster clock rates. The delay input is delay-matched to +// the sum pipe-line stages + +`timescale 1ps/1ps + +module ad_csc_1_add #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // all signed + + input clk, + input [24:0] data_1, + input [24:0] data_2, + input [24:0] data_3, + input [24:0] data_4, + output reg [ 7:0] data_p, + + // delay match + + input [DW:0] ddata_in, + output reg [DW:0] ddata_out); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // internal registers + + reg [DW:0] p1_ddata = 'd0; + reg [24:0] p1_data_1 = 'd0; + reg [24:0] p1_data_2 = 'd0; + reg [24:0] p1_data_3 = 'd0; + reg [24:0] p1_data_4 = 'd0; + reg [DW:0] p2_ddata = 'd0; + reg [24:0] p2_data_0 = 'd0; + reg [24:0] p2_data_1 = 'd0; + reg [DW:0] p3_ddata = 'd0; + reg [24:0] p3_data = 'd0; + + // internal signals + + wire [24:0] p1_data_1_p_s; + wire [24:0] p1_data_1_n_s; + wire [24:0] p1_data_1_s; + wire [24:0] p1_data_2_p_s; + wire [24:0] p1_data_2_n_s; + wire [24:0] p1_data_2_s; + wire [24:0] p1_data_3_p_s; + wire [24:0] p1_data_3_n_s; + wire [24:0] p1_data_3_s; + wire [24:0] p1_data_4_p_s; + wire [24:0] p1_data_4_n_s; + wire [24:0] p1_data_4_s; + + // pipe line stage 1, get the two's complement versions + + assign p1_data_1_p_s = {1'b0, data_1[23:0]}; + assign p1_data_1_n_s = ~p1_data_1_p_s + 1'b1; + assign p1_data_1_s = (data_1[24] == 1'b1) ? p1_data_1_n_s : p1_data_1_p_s; + + assign p1_data_2_p_s = {1'b0, data_2[23:0]}; + assign p1_data_2_n_s = ~p1_data_2_p_s + 1'b1; + assign p1_data_2_s = (data_2[24] == 1'b1) ? p1_data_2_n_s : p1_data_2_p_s; + + assign p1_data_3_p_s = {1'b0, data_3[23:0]}; + assign p1_data_3_n_s = ~p1_data_3_p_s + 1'b1; + assign p1_data_3_s = (data_3[24] == 1'b1) ? p1_data_3_n_s : p1_data_3_p_s; + + assign p1_data_4_p_s = {1'b0, data_4[23:0]}; + assign p1_data_4_n_s = ~p1_data_4_p_s + 1'b1; + assign p1_data_4_s = (data_4[24] == 1'b1) ? p1_data_4_n_s : p1_data_4_p_s; + + always @(posedge clk) begin + p1_ddata <= ddata_in; + p1_data_1 <= p1_data_1_s; + p1_data_2 <= p1_data_2_s; + p1_data_3 <= p1_data_3_s; + p1_data_4 <= p1_data_4_s; + end + + // pipe line stage 2, get the sum (intermediate, 4->2) + + always @(posedge clk) begin + p2_ddata <= p1_ddata; + p2_data_0 <= p1_data_1 + p1_data_2; + p2_data_1 <= p1_data_3 + p1_data_4; + end + + // pipe line stage 3, get the sum (final, 2->1) + + always @(posedge clk) begin + p3_ddata <= p2_ddata; + p3_data <= p2_data_0 + p2_data_1; + end + + // output registers, output is unsigned (0 if sum is < 0) and saturated. + // the inputs are expected to be 1.4.20 format (output is 8bits). + + always @(posedge clk) begin + ddata_out <= p3_ddata; + if (p3_data[24] == 1'b1) begin + data_p <= 8'h00; + end else if (p3_data[23:20] == 'd0) begin + data_p <= p3_data[19:12]; + end else begin + data_p <= 8'hff; + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_csc_1_mul.v b/src/adi/hdl/library/common/ad_csc_1_mul.v new file mode 100644 index 00000000..5847e128 --- /dev/null +++ b/src/adi/hdl/library/common/ad_csc_1_mul.v @@ -0,0 +1,97 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Color Space Conversion, multiplier. This is a simple partial product adder +// that generates the product of the two inputs. + +`timescale 1ps/1ps + +module ad_csc_1_mul #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // data_a is signed + + input clk, + input [16:0] data_a, + input [ 7:0] data_b, + output [24:0] data_p, + + // delay match + + input [(DELAY_DATA_WIDTH-1):0] ddata_in, + output [(DELAY_DATA_WIDTH-1):0] ddata_out); + + // internal registers + + reg [(DELAY_DATA_WIDTH-1):0] p1_ddata = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] p2_ddata = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] p3_ddata = 'd0; + reg p1_sign = 'd0; + reg p2_sign = 'd0; + reg p3_sign = 'd0; + + // internal signals + + wire [33:0] p3_data_s; + + // a/b reg, m-reg, p-reg delay match + + always @(posedge clk) begin + p1_ddata <= ddata_in; + p2_ddata <= p1_ddata; + p3_ddata <= p2_ddata; + end + + always @(posedge clk) begin + p1_sign <= data_a[16]; + p2_sign <= p1_sign; + p3_sign <= p2_sign; + end + + assign ddata_out = p3_ddata; + assign data_p = {p3_sign, p3_data_s[23:0]}; + + ad_mul ad_mul_1 ( + .clk(clk), + .data_a({1'b0, data_a[15:0]}), + .data_b({9'b0, data_b}), + .data_p(p3_data_s), + .ddata_in(16'h0), + .ddata_out()); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_csc_CrYCb2RGB.v b/src/adi/hdl/library/common/ad_csc_CrYCb2RGB.v new file mode 100644 index 00000000..12ec8c07 --- /dev/null +++ b/src/adi/hdl/library/common/ad_csc_CrYCb2RGB.v @@ -0,0 +1,103 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Transmit HDMI, CrYCb to RGB conversion +// The multiplication coefficients are in 1.4.12 format +// The addition coefficients are in 1.12.12 format +// R = (+408.583/256)*Cr + (+298.082/256)*Y + ( 000.000/256)*Cb + (-222.921); +// G = (-208.120/256)*Cr + (+298.082/256)*Y + (-100.291/256)*Cb + (+135.576); +// B = ( 000.000/256)*Cr + (+298.082/256)*Y + (+516.412/256)*Cb + (-276.836); + +`timescale 1ns/100ps + +module ad_csc_CrYCb2RGB #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // Cr-Y-Cb inputs + + input clk, + input [DW:0] CrYCb_sync, + input [23:0] CrYCb_data, + + // R-G-B outputs + + output [DW:0] RGB_sync, + output [23:0] RGB_data); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // red + + ad_csc_1 #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH)) i_csc_1_R ( + .clk (clk), + .sync (CrYCb_sync), + .data (CrYCb_data), + .C1 (17'h01989), + .C2 (17'h012a1), + .C3 (17'h00000), + .C4 (25'h10deebc), + .csc_sync_1 (RGB_sync), + .csc_data_1 (RGB_data[23:16])); + + // green + + ad_csc_1 #(.DELAY_DATA_WIDTH(1)) i_csc_1_G ( + .clk (clk), + .sync (1'd0), + .data (CrYCb_data), + .C1 (17'h10d01), + .C2 (17'h012a1), + .C3 (17'h10644), + .C4 (25'h0087937), + .csc_sync_1 (), + .csc_data_1 (RGB_data[15:8])); + + // blue + + ad_csc_1 #(.DELAY_DATA_WIDTH(1)) i_csc_1_B ( + .clk (clk), + .sync (1'd0), + .data (CrYCb_data), + .C1 (17'h00000), + .C2 (17'h012a1), + .C3 (17'h02046), + .C4 (25'h1114d60), + .csc_sync_1 (), + .csc_data_1 (RGB_data[7:0])); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_csc_RGB2CrYCb.v b/src/adi/hdl/library/common/ad_csc_RGB2CrYCb.v new file mode 100644 index 00000000..4b7e90ee --- /dev/null +++ b/src/adi/hdl/library/common/ad_csc_RGB2CrYCb.v @@ -0,0 +1,103 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Transmit HDMI, RGB to CrYCb conversion +// The multiplication coefficients are in 1.4.12 format +// The addition coefficients are in 1.12.12 format +// Cr = (+112.439/256)*R + (-094.154/256)*G + (-018.285/256)*B + 128; +// Y = (+065.738/256)*R + (+129.057/256)*G + (+025.064/256)*B + 16; +// Cb = (-037.945/256)*R + (-074.494/256)*G + (+112.439/256)*B + 128; + +`timescale 1ns/100ps + +module ad_csc_RGB2CrYCb #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // R-G-B inputs + + input clk, + input [DW:0] RGB_sync, + input [23:0] RGB_data, + + // Cr-Y-Cb outputs + + output [DW:0] CrYCb_sync, + output [23:0] CrYCb_data); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // Cr (red-diff) + + ad_csc_1 #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH)) i_csc_1_Cr ( + .clk (clk), + .sync (RGB_sync), + .data (RGB_data), + .C1 (17'h00707), + .C2 (17'h105e2), + .C3 (17'h10124), + .C4 (25'h0080000), + .csc_sync_1 (CrYCb_sync), + .csc_data_1 (CrYCb_data[23:16])); + + // Y (luma) + + ad_csc_1 #(.DELAY_DATA_WIDTH(1)) i_csc_1_Y ( + .clk (clk), + .sync (1'd0), + .data (RGB_data), + .C1 (17'h0041b), + .C2 (17'h00810), + .C3 (17'h00191), + .C4 (25'h0010000), + .csc_sync_1 (), + .csc_data_1 (CrYCb_data[15:8])); + + // Cb (blue-diff) + + ad_csc_1 #(.DELAY_DATA_WIDTH(1)) i_csc_1_Cb ( + .clk (clk), + .sync (1'd0), + .data (RGB_data), + .C1 (17'h1025f), + .C2 (17'h104a7), + .C3 (17'h00707), + .C4 (25'h0080000), + .csc_sync_1 (), + .csc_data_1 (CrYCb_data[7:0])); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_datafmt.v b/src/adi/hdl/library/common/ad_datafmt.v new file mode 100644 index 00000000..0d47f7f8 --- /dev/null +++ b/src/adi/hdl/library/common/ad_datafmt.v @@ -0,0 +1,108 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// data format (offset binary or 2's complement only) + +`timescale 1ps/1ps + +module ad_datafmt #( + + // data bus width + + parameter DATA_WIDTH = 16, + parameter DISABLE = 0) ( + + // data path + + input clk, + input valid, + input [(DATA_WIDTH-1):0] data, + output valid_out, + output [15:0] data_out, + + // control signals + + input dfmt_enable, + input dfmt_type, + input dfmt_se); + + // internal registers + + reg valid_int = 'd0; + reg [15:0] data_int = 'd0; + + // internal signals + + wire type_s; + wire [15:0] data_out_s; + + // data-path disable + + generate + if (DISABLE == 1) begin + assign valid_out = valid; + assign data_out = data; + end else begin + assign valid_out = valid_int; + assign data_out = data_int; + end + endgenerate + + // if offset-binary convert to 2's complement first + + assign type_s = dfmt_enable & dfmt_type; + + generate + if (DATA_WIDTH < 16) begin + wire signext_s; + wire sign_s; + + assign signext_s = dfmt_enable & dfmt_se; + assign sign_s = signext_s & (type_s ^ data[(DATA_WIDTH-1)]); + assign data_out_s[15:DATA_WIDTH] = {(16-DATA_WIDTH){sign_s}}; + end + endgenerate + + assign data_out_s[(DATA_WIDTH-1)] = type_s ^ data[(DATA_WIDTH-1)]; + assign data_out_s[(DATA_WIDTH-2):0] = data[(DATA_WIDTH-2):0]; + + always @(posedge clk) begin + valid_int <= valid; + data_int <= data_out_s[15:0]; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_dds.v b/src/adi/hdl/library/common/ad_dds.v new file mode 100644 index 00000000..76cf18aa --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds.v @@ -0,0 +1,132 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +// single channel dds (dual tone) +module ad_dds #( + + parameter DISABLE = 0, + // range 8-24 + parameter DDS_DW = 16, + // range 8-16 (FIX ME) + parameter PHASE_DW = 16, + // set 1 for CORDIC or 2 for Polynomial + parameter DDS_TYPE = 1, + // range 8-24 + parameter CORDIC_DW = 16, + // range 8-24 (make sure CORDIC_PHASE_DW < CORDIC_DW) + parameter CORDIC_PHASE_DW = 16, + // the clock radtio between the device clock(sample rate) and the dac_core clock + // 2^N, 1 1)begin + dac_dds_phase_0[i] <= dac_dds_phase_0[i-1] + tone_1_freq_word; + dac_dds_phase_1[i] <= dac_dds_phase_1[i-1] + tone_2_freq_word; + end + end else if (dac_valid == 1'b1) begin + dac_dds_phase_0[i] <= dac_dds_phase_0[i] + dac_dds_incr_0; + dac_dds_phase_1[i] <= dac_dds_phase_1[i] + dac_dds_incr_1; + end + end + + // phase to amplitude convertor + ad_dds_2 #( + .DDS_DW (DDS_DW), + .PHASE_DW (PHASE_DW), + .DDS_TYPE (DDS_TYPE), + .CORDIC_DW (CORDIC_DW), + .CORDIC_PHASE_DW (CORDIC_PHASE_DW)) + i_dds_2 ( + .clk (clk), + .dds_format (dac_dds_format), + .dds_phase_0 (dac_dds_phase_0[i]), + .dds_scale_0 (tone_1_scale), + .dds_phase_1 (dac_dds_phase_1[i]), + .dds_scale_1 (tone_2_scale), + .dds_data (dac_dds_data_s[(DDS_DW*i)-1:DDS_DW*(i-1)])); + end + end + endgenerate + +endmodule diff --git a/src/adi/hdl/library/common/ad_dds_1.v b/src/adi/hdl/library/common/ad_dds_1.v new file mode 100644 index 00000000..7c41b15e --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds_1.v @@ -0,0 +1,115 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_dds_1 #( + + // parameters + + parameter DDS_TYPE = 1, + parameter DDS_D_DW = 16, + parameter DDS_P_DW = 16) ( + + // interface + + input clk, + input [DDS_P_DW-1:0] angle, + input [ 15:0] scale, + output reg [DDS_D_DW-1:0] dds_data); + + // local parameters + + localparam DDS_CORDIC_TYPE = 1; + localparam DDS_POLINOMIAL_TYPE = 2; + + // internal signals + + wire [ DDS_D_DW-1:0] sine_s; + wire [DDS_D_DW+17:0] s1_data_s; + + // sine + + generate + if (DDS_TYPE == DDS_CORDIC_TYPE) begin + + ad_dds_sine_cordic #( + .CORDIC_DW(DDS_D_DW), + .PHASE_DW(DDS_P_DW), + .DELAY_DW(1)) + i_dds_sine ( + .clk (clk), + .angle (angle), + .sine (sine_s), + .cosine (), + .ddata_in (1'b0), + .ddata_out ()); + + end else begin + + ad_dds_sine i_dds_sine ( + .clk (clk), + .angle (angle), + .sine (sine_s), + .ddata_in (1'b0), + .ddata_out ()); + end + endgenerate + + // scale for a sine generator + + ad_mul #( + .A_DATA_WIDTH(DDS_D_DW + 1), + .B_DATA_WIDTH(17), + .DELAY_DATA_WIDTH(1)) + i_dds_scale ( + .clk (clk), + .data_a ({sine_s[DDS_D_DW-1], sine_s}), + .data_b ({scale[15], scale}), + .data_p (s1_data_s), + .ddata_in (1'b0), + .ddata_out ()); + + // dds data + + always @(posedge clk) begin + //15'h8000 is the maximum scale + dds_data <= s1_data_s[DDS_D_DW+13:14]; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_dds_2.v b/src/adi/hdl/library/common/ad_dds_2.v new file mode 100644 index 00000000..3f965bc3 --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds_2.v @@ -0,0 +1,156 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_dds_2 #( + + // Range = 8-24 + parameter DDS_DW = 16, + // Range = 8-24 + parameter PHASE_DW = 16, + // Set 1 for CORDIC or 2 for Polynomial + parameter DDS_TYPE = 1, + // Range = 8-24 + parameter CORDIC_DW = 16, + // Range = 8-24 ( make sure CORDIC_PHASE_DW < CORDIC_DW) + parameter CORDIC_PHASE_DW = 16) ( + + // interface + + input clk, + input dds_format, + input [PHASE_DW-1:0] dds_phase_0, + input [ 15:0] dds_scale_0, + input [PHASE_DW-1:0] dds_phase_1, + input [ 15:0] dds_scale_1, + output [ DDS_DW-1:0] dds_data); + + // Local parameters + + localparam CORDIC = 1; + localparam POLYNOMIAL = 2; + + // The width for Polynomial DDS is fixed (16) + localparam DDS_D_DW = (DDS_TYPE == CORDIC) ? CORDIC_DW : 16; + localparam DDS_P_DW = (DDS_TYPE == CORDIC) ? CORDIC_PHASE_DW : 16; + // concatenation or truncation width + localparam C_T_WIDTH = (DDS_D_DW > DDS_DW) ? (DDS_D_DW - DDS_DW) : (DDS_DW - DDS_D_DW); + + // internal registers + + reg [ DDS_DW-1:0] dds_data_width = 0; + reg [DDS_D_DW-1:0] dds_data_rownd = 0; + reg [DDS_D_DW-1:0] dds_data_int = 0; + reg [ 15:0] dds_scale_0_d = 0; + reg [ 15:0] dds_scale_1_d = 0; + reg [ DDS_DW-1:0] dds_data_out = 0; + + // internal signals + + wire [DDS_D_DW-1:0] dds_data_0_s; + wire [DDS_D_DW-1:0] dds_data_1_s; + wire [DDS_P_DW-1:0] dds_phase_0_s; + wire [DDS_P_DW-1:0] dds_phase_1_s; + + generate + // dds channel output + assign dds_data = dds_data_out; + + // output data format + always @(posedge clk) begin + dds_data_out[DDS_DW-1] <= dds_data_width[DDS_DW-1] ^ dds_format; + dds_data_out[DDS_DW-2: 0] <= dds_data_width[DDS_DW-2: 0]; + end + + // set desired data width + always @(posedge clk) begin + if (DDS_DW < DDS_D_DW) begin // truncation + // fair rownding + dds_data_rownd <= dds_data_int + {(C_T_WIDTH){dds_data_int[DDS_D_DW-1]}}; + dds_data_width <= dds_data_rownd[DDS_D_DW-1:DDS_D_DW-DDS_DW]; + end else begin // concatenation + dds_data_width <= dds_data_int << C_T_WIDTH; + end + end + + // dual tone + always @(posedge clk) begin + dds_data_int <= dds_data_0_s + dds_data_1_s; + end + + always @(posedge clk) begin + dds_scale_0_d <= dds_scale_0; + dds_scale_1_d <= dds_scale_1; + end + + // phase + if (DDS_P_DW > PHASE_DW) begin + assign dds_phase_0_s = {dds_phase_0,{DDS_P_DW-PHASE_DW{1'b0}}}; + assign dds_phase_1_s = {dds_phase_1,{DDS_P_DW-PHASE_DW{1'b0}}}; + end else begin + assign dds_phase_0_s = dds_phase_0[(PHASE_DW-1):PHASE_DW-DDS_P_DW]; + assign dds_phase_1_s = dds_phase_1[(PHASE_DW-1):PHASE_DW-DDS_P_DW]; + end + + // dds-1 + + ad_dds_1 #( + .DDS_TYPE(DDS_TYPE), + .DDS_D_DW(DDS_D_DW), + .DDS_P_DW(DDS_P_DW)) + i_dds_1_0 ( + .clk (clk), + .angle (dds_phase_0_s), + .scale (dds_scale_0_d), + .dds_data (dds_data_0_s)); + + // dds-2 + + ad_dds_1 #( + .DDS_TYPE(DDS_TYPE), + .DDS_D_DW(DDS_D_DW), + .DDS_P_DW(DDS_P_DW)) + i_dds_1_1 ( + .clk (clk), + .angle (dds_phase_1_s), + .scale (dds_scale_1_d), + .dds_data (dds_data_1_s)); + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_dds_cordic_pipe.v b/src/adi/hdl/library/common/ad_dds_cordic_pipe.v new file mode 100644 index 00000000..926c47d1 --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds_cordic_pipe.v @@ -0,0 +1,100 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_dds_cordic_pipe#( + + // parameters + + // Range = N/A + parameter P_DW = 16, + // Range = N/A + parameter D_DW = 16, + // Range = N/A + parameter DELAY_DW = 1, + // Range = 0-(DW - 1) + parameter SHIFT = 0) ( + + // Interface + + input clk, + (* keep = "TRUE" *) input dir, + (* keep = "TRUE" *) input [ D_DW-1:0] dataa_x, + (* keep = "TRUE" *) input [ D_DW-1:0] dataa_y, + (* keep = "TRUE" *) input [ P_DW-1:0] dataa_z, + (* keep = "TRUE" *) input [ P_DW-1:0] datab_z, + (* keep = "TRUE" *) output reg [ D_DW-1:0] result_x, + (* keep = "TRUE" *) output reg [ D_DW-1:0] result_y, + (* keep = "TRUE" *) output reg [ P_DW-1:0] result_z, + input [DELAY_DW:1] data_delay_in, + output [DELAY_DW:1] data_delay_out); + + // Registers Declarations + + reg [DELAY_DW:1] data_delay = 'd0; + + // Wires Declarations + + wire [ D_DW-1:0] sgn_shift_x; + wire [ D_DW-1:0] sgn_shift_y; + wire dir_inv = ~dir; + + // Sign shift + + assign sgn_shift_x = {{SHIFT{dataa_x[D_DW-1]}}, dataa_x[D_DW-1:SHIFT]}; + assign sgn_shift_y = {{SHIFT{dataa_y[D_DW-1]}}, dataa_y[D_DW-1:SHIFT]}; + + // Stage rotation + + always @(posedge clk) begin + result_x <= dataa_x + ({D_DW{dir_inv}} ^ sgn_shift_y) + dir_inv; + result_y <= dataa_y + ({D_DW{dir}} ^ sgn_shift_x) + dir; + result_z <= dataa_z + ({P_DW{dir_inv}} ^ datab_z) + dir_inv; + end + + // Delay data (if used) + + generate + if (DELAY_DW > 1) begin + always @(posedge clk) begin + data_delay <= data_delay_in; + end + end + endgenerate + + assign data_delay_out = data_delay; + +endmodule diff --git a/src/adi/hdl/library/common/ad_dds_sine.v b/src/adi/hdl/library/common/ad_dds_sine.v new file mode 100644 index 00000000..b1755a0f --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds_sine.v @@ -0,0 +1,206 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// this is a sine function (approximate), the basic idea is to approximate sine as a +// polynomial function (there are a lot of stuff about this on the web) + +`timescale 1ns/100ps + +module ad_dds_sine #( + + parameter DELAY_DATA_WIDTH = 16) ( + + // sine = sin(angle) + + input clk, + input [15:0] angle, + output [15:0] sine, + input [(DELAY_DATA_WIDTH-1):0] ddata_in, + output [(DELAY_DATA_WIDTH-1):0] ddata_out); + + // internal registers + + reg [33:0] s1_data_p = 'd0; + reg [33:0] s1_data_n = 'd0; + reg [15:0] s1_angle = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s1_ddata = 'd0; + reg [18:0] s2_data_0 = 'd0; + reg [18:0] s2_data_1 = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s2_ddata = 'd0; + reg [18:0] s3_data = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s3_ddata = 'd0; + reg [33:0] s4_data2_p = 'd0; + reg [33:0] s4_data2_n = 'd0; + reg [16:0] s4_data1_p = 'd0; + reg [16:0] s4_data1_n = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s4_ddata = 'd0; + reg [16:0] s5_data2_0 = 'd0; + reg [16:0] s5_data2_1 = 'd0; + reg [16:0] s5_data1 = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s5_ddata = 'd0; + reg [16:0] s6_data2 = 'd0; + reg [16:0] s6_data1 = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s6_ddata = 'd0; + reg [33:0] s7_data = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] s7_ddata = 'd0; + reg [15:0] sine_int = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] ddata_out_int = 'd0; + + // internal signals + + wire [15:0] angle_s; + wire [33:0] s1_data_s; + wire [(DELAY_DATA_WIDTH-1):0] s1_ddata_s; + wire [15:0] s1_angle_s; + wire [33:0] s4_data2_s; + wire [(DELAY_DATA_WIDTH-1):0] s4_ddata_s; + wire [16:0] s4_data1_s; + wire [33:0] s7_data2_s; + wire [33:0] s7_data1_s; + wire [(DELAY_DATA_WIDTH-1):0] s7_ddata_s; + + // make angle 2's complement + + assign angle_s = {~angle[15], angle[14:0]}; + + // level 1 - intermediate + + ad_mul #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH+16)) i_mul_s1 ( + .clk (clk), + .data_a ({angle_s[15], angle_s}), + .data_b ({angle_s[15], angle_s}), + .data_p (s1_data_s), + .ddata_in ({ddata_in, angle_s}), + .ddata_out ({s1_ddata_s, s1_angle_s})); + + // 2's complement versions + + always @(posedge clk) begin + s1_data_p <= s1_data_s; + s1_data_n <= ~s1_data_s + 1'b1; + s1_angle <= s1_angle_s; + s1_ddata <= s1_ddata_s; + end + + // select partial products + + always @(posedge clk) begin + s2_data_0 <= (s1_angle[15] == 1'b0) ? s1_data_n[31:13] : s1_data_p[31:13]; + s2_data_1 <= {s1_angle[15], s1_angle[15:0], 2'b00}; + s2_ddata <= s1_ddata; + end + + // unit-sine + + always @(posedge clk) begin + s3_data <= s2_data_0 + s2_data_1; + s3_ddata <= s2_ddata; + end + + // level 2 - final + + ad_mul #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH+17)) i_mul_s2 ( + .clk (clk), + .data_a (s3_data[16:0]), + .data_b (s3_data[16:0]), + .data_p (s4_data2_s), + .ddata_in ({s3_ddata, s3_data[16:0]}), + .ddata_out ({s4_ddata_s, s4_data1_s})); + + // 2's complement versions + + always @(posedge clk) begin + s4_data2_p <= s4_data2_s; + s4_data2_n <= ~s4_data2_s + 1'b1; + s4_data1_p <= s4_data1_s; + s4_data1_n <= ~s4_data1_s + 1'b1; + s4_ddata <= s4_ddata_s; + end + + // select partial products + + always @(posedge clk) begin + s5_data2_0 <= (s4_data1_p[16] == 1'b1) ? s4_data2_n[31:15] : s4_data2_p[31:15]; + s5_data2_1 <= s4_data1_n; + s5_data1 <= s4_data1_p; + s5_ddata <= s4_ddata; + end + + // corrected-sine + + always @(posedge clk) begin + s6_data2 <= s5_data2_0 + s5_data2_1; + s6_data1 <= s5_data1; + s6_ddata <= s5_ddata; + end + + // full-scale + + ad_mul #(.DELAY_DATA_WIDTH(1)) i_mul_s3_2 ( + .clk (clk), + .data_a (s6_data2), + .data_b (17'h1d08), + .data_p (s7_data2_s), + .ddata_in (1'b0), + .ddata_out ()); + + ad_mul #(.DELAY_DATA_WIDTH(DELAY_DATA_WIDTH)) i_mul_s3_1 ( + .clk (clk), + .data_a (s6_data1), + .data_b (17'h7fff), + .data_p (s7_data1_s), + .ddata_in (s6_ddata), + .ddata_out (s7_ddata_s)); + + // corrected sum + + always @(posedge clk) begin + s7_data <= s7_data2_s + s7_data1_s; + s7_ddata <= s7_ddata_s; + end + + // output registers + + assign sine = sine_int; + assign ddata_out = ddata_out_int; + + always @(posedge clk) begin + sine_int <= s7_data[30:15]; + ddata_out_int <= s7_ddata; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_dds_sine_cordic.v b/src/adi/hdl/library/common/ad_dds_sine_cordic.v new file mode 100644 index 00000000..66eba7e3 --- /dev/null +++ b/src/adi/hdl/library/common/ad_dds_sine_cordic.v @@ -0,0 +1,430 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_dds_sine_cordic #( + + // Range = 8-24 + parameter PHASE_DW = 16, + // Range = 8-24 + parameter CORDIC_DW = 16, + // Range = N/A + parameter DELAY_DW = 1) ( + + // interface + + input clk, + input [ PHASE_DW-1:0] angle, + output reg [CORDIC_DW-1:0] sine, + output reg [CORDIC_DW-1:0] cosine, + input [ DELAY_DW-1:0] ddata_in, + output reg [ DELAY_DW-1:0] ddata_out); + + // Local Parameters + localparam LUT_FSCALE = 1 << (PHASE_DW); + + // 1.64676025812 =~ system gain + localparam X_FSCALE = 1 << (CORDIC_DW); + localparam APROX_DW_GAIN_ERR = (CORDIC_DW < 21) ? 4 : + (CORDIC_DW <= 24) ? 7 : 0; + // ((2^N)/2)/1.647... + localparam [CORDIC_DW-1:0] X_VALUE = ((X_FSCALE/2)/(1.64676))-APROX_DW_GAIN_ERR; + + // Registers Declarations + + reg [CORDIC_DW-1:0] x0 = 'd0; + reg [CORDIC_DW-1:0] y0 = 'd0; + reg [ PHASE_DW-1:0] z0 = 'd0; + + // Wires Declarations + + wire [CORDIC_DW-1:0] x_s [0:CORDIC_DW-1]; + wire [CORDIC_DW-1:0] y_s [0:CORDIC_DW-1]; + wire [ PHASE_DW-1:0] z_s [0:CORDIC_DW-1]; + wire [ DELAY_DW-1:0] data_in_d [0:CORDIC_DW-1]; + wire [ PHASE_DW-1:0] atan_table[0:CORDIC_DW-2]; + wire [ 1:0] quadrant; + + // arc tangent LUT + + generate + if (PHASE_DW == 24) begin + assign atan_table[ 0] = 24'd2097152; // 45.0000000000000 + assign atan_table[ 1] = 24'd1238021; // 26.5650511770780 + assign atan_table[ 2] = 24'd654136; // 14.0362434679265 + assign atan_table[ 3] = 24'd332050; // 7.12501634890180 + assign atan_table[ 4] = 24'd166669; // 3.57633437499735 + assign atan_table[ 5] = 24'd83416; // 1.78991060824607 + assign atan_table[ 6] = 24'd41718; // 0.89517371021107 + assign atan_table[ 7] = 24'd20860; // 0.44761417086055 + assign atan_table[ 8] = 24'd10430; // 0.22381050036853 + assign atan_table[ 9] = 24'd5215; // 0.11190567706620 + assign atan_table[10] = 24'd2608; // 0.05595289189380 + assign atan_table[11] = 24'd1304; // 0.02797645261700 + assign atan_table[12] = 24'd652; // 0.01398822714226 + assign atan_table[13] = 24'd326; // 0.00699411367535 + assign atan_table[14] = 24'd163; // 0.00349705685070 + assign atan_table[15] = 24'd81; // 0.00174852842698 + assign atan_table[16] = 24'd41; // 0.00087426421369 + assign atan_table[17] = 24'd20; // 0.00043713210687 + assign atan_table[18] = 24'd10; // 0.00021856605343 + assign atan_table[19] = 24'd5; // 0.00010928302672 + assign atan_table[20] = 24'd3; // 0.00005464151336 + assign atan_table[21] = 24'd1; // 0.00002732075668 + assign atan_table[22] = 24'd1; // 0.00001366037834 + end else if (PHASE_DW == 23) begin + assign atan_table[ 0] = 23'd1048576; // 45.0000000000000 + assign atan_table[ 1] = 23'd619011; // 26.5650511770780 + assign atan_table[ 2] = 23'd327068; // 14.0362434679265 + assign atan_table[ 3] = 23'd166025; // 7.12501634890180 + assign atan_table[ 4] = 23'd83335; // 3.57633437499735 + assign atan_table[ 5] = 23'd41708; // 1.78991060824607 + assign atan_table[ 6] = 23'd20859; // 0.89517371021107 + assign atan_table[ 7] = 23'd10430; // 0.44761417086055 + assign atan_table[ 8] = 23'd5215; // 0.22381050036853 + assign atan_table[ 9] = 23'd2608; // 0.11190567706620 + assign atan_table[10] = 23'd1304; // 0.05595289189380 + assign atan_table[11] = 23'd652; // 0.02797645261700 + assign atan_table[12] = 23'd326; // 0.01398822714226 + assign atan_table[13] = 23'd163; // 0.00699411367535 + assign atan_table[14] = 23'd81; // 0.00349705685070 + assign atan_table[15] = 23'd41; // 0.00174852842698 + assign atan_table[16] = 23'd20; // 0.00087426421369 + assign atan_table[17] = 23'd10; // 0.00043713210687 + assign atan_table[18] = 23'd5; // 0.00021856605343 + assign atan_table[19] = 23'd3; // 0.00010928302672 + assign atan_table[20] = 23'd1; // 0.00005464151336 + assign atan_table[21] = 23'd1; // 0.00002732075668 + end else if (PHASE_DW == 22) begin + assign atan_table[ 0] = 22'd524288; // ... + assign atan_table[ 1] = 22'd309505; + assign atan_table[ 2] = 22'd163534; + assign atan_table[ 3] = 22'd83012; + assign atan_table[ 4] = 22'd41667; + assign atan_table[ 5] = 22'd20854; + assign atan_table[ 6] = 22'd10430; + assign atan_table[ 7] = 22'd5215; + assign atan_table[ 8] = 22'd2608; + assign atan_table[ 9] = 22'd1304; + assign atan_table[10] = 22'd652; + assign atan_table[11] = 22'd326; + assign atan_table[12] = 22'd163; + assign atan_table[13] = 22'd81; + assign atan_table[14] = 22'd41; + assign atan_table[15] = 22'd20; + assign atan_table[16] = 22'd10; + assign atan_table[17] = 22'd5; + assign atan_table[18] = 22'd3; + assign atan_table[19] = 22'd1; + assign atan_table[20] = 22'd1; + end else if (PHASE_DW == 21) begin + assign atan_table[ 0] = 21'd262144; + assign atan_table[ 1] = 21'd154753; + assign atan_table[ 2] = 21'd81767; + assign atan_table[ 3] = 21'd41506; + assign atan_table[ 4] = 21'd20834; + assign atan_table[ 5] = 21'd10427; + assign atan_table[ 6] = 21'd5215; + assign atan_table[ 7] = 21'd2608; + assign atan_table[ 8] = 21'd1304; + assign atan_table[ 9] = 21'd652; + assign atan_table[10] = 21'd326; + assign atan_table[11] = 21'd163; + assign atan_table[12] = 21'd81; + assign atan_table[13] = 21'd41; + assign atan_table[14] = 21'd20; + assign atan_table[15] = 21'd10; + assign atan_table[16] = 21'd5; + assign atan_table[17] = 21'd3; + assign atan_table[18] = 21'd1; + assign atan_table[19] = 21'd1; + end else if (PHASE_DW == 20) begin + assign atan_table[ 0] = 20'd131072; + assign atan_table[ 1] = 20'd77376; + assign atan_table[ 2] = 20'd40884; + assign atan_table[ 3] = 20'd20753; + assign atan_table[ 4] = 20'd10417; + assign atan_table[ 5] = 20'd5213; + assign atan_table[ 6] = 20'd2607; + assign atan_table[ 7] = 20'd1304; + assign atan_table[ 8] = 20'd652; + assign atan_table[ 9] = 20'd326; + assign atan_table[10] = 20'd163; + assign atan_table[11] = 20'd81; + assign atan_table[12] = 20'd41; + assign atan_table[13] = 20'd20; + assign atan_table[14] = 20'd10; + assign atan_table[15] = 20'd5; + assign atan_table[16] = 20'd3; + assign atan_table[17] = 20'd1; + assign atan_table[18] = 20'd1; + end else if (PHASE_DW == 19) begin + assign atan_table[ 0] = 19'd65536; + assign atan_table[ 1] = 19'd38688; + assign atan_table[ 2] = 19'd20442; + assign atan_table[ 3] = 19'd10377; + assign atan_table[ 4] = 19'd5208; + assign atan_table[ 5] = 19'd2607; + assign atan_table[ 6] = 19'd1304; + assign atan_table[ 7] = 19'd652; + assign atan_table[ 8] = 19'd326; + assign atan_table[ 9] = 19'd163; + assign atan_table[10] = 19'd81; + assign atan_table[11] = 19'd41; + assign atan_table[12] = 19'd20; + assign atan_table[13] = 19'd10; + assign atan_table[14] = 19'd5; + assign atan_table[15] = 19'd3; + assign atan_table[16] = 19'd1; + assign atan_table[17] = 19'd1; + end else if (PHASE_DW == 18) begin + assign atan_table[ 0] = 18'd32768; + assign atan_table[ 1] = 18'd19344; + assign atan_table[ 2] = 18'd10221; + assign atan_table[ 3] = 18'd5188; + assign atan_table[ 4] = 18'd2604; + assign atan_table[ 5] = 18'd1303; + assign atan_table[ 6] = 18'd652; + assign atan_table[ 7] = 18'd326; + assign atan_table[ 8] = 18'd163; + assign atan_table[ 9] = 18'd81; + assign atan_table[10] = 18'd41; + assign atan_table[11] = 18'd20; + assign atan_table[12] = 18'd10; + assign atan_table[13] = 18'd5; + assign atan_table[14] = 18'd3; + assign atan_table[15] = 18'd1; + assign atan_table[16] = 18'd1; + end else if (PHASE_DW == 17) begin + assign atan_table[ 0] = 17'd16384; + assign atan_table[ 1] = 17'd9672; + assign atan_table[ 2] = 17'd5110; + assign atan_table[ 3] = 17'd2594; + assign atan_table[ 4] = 17'd1302; + assign atan_table[ 5] = 17'd652; + assign atan_table[ 6] = 17'd326; + assign atan_table[ 7] = 17'd163; + assign atan_table[ 8] = 17'd81; + assign atan_table[ 9] = 17'd41; + assign atan_table[10] = 17'd20; + assign atan_table[11] = 17'd10; + assign atan_table[12] = 17'd5; + assign atan_table[13] = 17'd3; + assign atan_table[14] = 17'd1; + assign atan_table[15] = 17'd1; + end else if (PHASE_DW == 16) begin + assign atan_table[ 0] = 16'd8192; + assign atan_table[ 1] = 16'd4836; + assign atan_table[ 2] = 16'd2555; + assign atan_table[ 3] = 16'd1297; + assign atan_table[ 4] = 16'd651; + assign atan_table[ 5] = 16'd326; + assign atan_table[ 6] = 16'd163; + assign atan_table[ 7] = 16'd81; + assign atan_table[ 8] = 16'd41; + assign atan_table[ 9] = 16'd20; + assign atan_table[10] = 16'd10; + assign atan_table[11] = 16'd5; + assign atan_table[12] = 16'd3; + assign atan_table[13] = 16'd1; + assign atan_table[14] = 16'd1; + end else if (PHASE_DW == 15) begin + assign atan_table[ 0] = 15'd4096; + assign atan_table[ 1] = 15'd2418; + assign atan_table[ 2] = 15'd1278; + assign atan_table[ 3] = 15'd649; + assign atan_table[ 4] = 15'd326; + assign atan_table[ 5] = 15'd163; + assign atan_table[ 6] = 15'd81; + assign atan_table[ 7] = 15'd41; + assign atan_table[ 8] = 15'd20; + assign atan_table[ 9] = 15'd10; + assign atan_table[10] = 15'd5; + assign atan_table[11] = 15'd3; + assign atan_table[12] = 15'd1; + assign atan_table[13] = 15'd1; + end else if (PHASE_DW == 14) begin + assign atan_table[ 0] = 14'd2048; + assign atan_table[ 1] = 14'd1209; + assign atan_table[ 2] = 14'd639; + assign atan_table[ 3] = 14'd324; + assign atan_table[ 4] = 14'd163; + assign atan_table[ 5] = 14'd81; + assign atan_table[ 6] = 14'd41; + assign atan_table[ 7] = 14'd20; + assign atan_table[ 8] = 14'd10; + assign atan_table[ 9] = 14'd5; + assign atan_table[10] = 14'd3; + assign atan_table[11] = 14'd1; + assign atan_table[12] = 14'd1; + end else if (PHASE_DW == 13) begin + assign atan_table[ 0] = 13'd1024; + assign atan_table[ 1] = 13'd605; + assign atan_table[ 2] = 13'd319; + assign atan_table[ 3] = 13'd162; + assign atan_table[ 4] = 13'd81; + assign atan_table[ 5] = 13'd41; + assign atan_table[ 6] = 13'd20; + assign atan_table[ 7] = 13'd10; + assign atan_table[ 8] = 13'd5; + assign atan_table[ 9] = 13'd3; + assign atan_table[10] = 13'd1; + assign atan_table[11] = 13'd1; + end else if (PHASE_DW == 12) begin + assign atan_table[ 0] = 12'd512; + assign atan_table[ 1] = 12'd302; + assign atan_table[ 2] = 12'd160; + assign atan_table[ 3] = 12'd81; + assign atan_table[ 4] = 12'd41; + assign atan_table[ 5] = 12'd20; + assign atan_table[ 6] = 12'd10; + assign atan_table[ 7] = 12'd5; + assign atan_table[ 8] = 12'd3; + assign atan_table[ 9] = 12'd1; + assign atan_table[10] = 12'd1; + end else if (PHASE_DW == 11) begin + assign atan_table[ 0] = 11'd256; + assign atan_table[ 1] = 11'd151; + assign atan_table[ 2] = 11'd80; + assign atan_table[ 3] = 11'd41; + assign atan_table[ 4] = 11'd20; + assign atan_table[ 5] = 11'd10; + assign atan_table[ 6] = 11'd5; + assign atan_table[ 7] = 11'd3; + assign atan_table[ 8] = 11'd1; + assign atan_table[ 9] = 11'd1; + end else if (PHASE_DW == 10) begin + assign atan_table[ 0] = 10'd128; + assign atan_table[ 1] = 10'd76; + assign atan_table[ 2] = 10'd40; + assign atan_table[ 3] = 10'd20; + assign atan_table[ 4] = 10'd10; + assign atan_table[ 5] = 10'd5; + assign atan_table[ 6] = 10'd3; + assign atan_table[ 7] = 10'd1; + assign atan_table[ 8] = 10'd1; + end else if (PHASE_DW == 9) begin + assign atan_table[ 0] = 9'd64; + assign atan_table[ 1] = 9'd38; + assign atan_table[ 2] = 9'd20; + assign atan_table[ 3] = 9'd10; + assign atan_table[ 4] = 9'd5; + assign atan_table[ 5] = 9'd3; + assign atan_table[ 6] = 9'd1; + assign atan_table[ 7] = 9'd1; + end else if (PHASE_DW == 8) begin + assign atan_table[ 0] = 8'd32; + assign atan_table[ 1] = 8'd19; + assign atan_table[ 2] = 8'd10; + assign atan_table[ 3] = 8'd5; + assign atan_table[ 4] = 8'd3; + assign atan_table[ 5] = 8'd1; + assign atan_table[ 6] = 8'd1; + end + endgenerate + + // pre-rotating + + // first two bits represent the quadrant in the unit circle + assign quadrant = angle[PHASE_DW-1:PHASE_DW-2]; + + always @(posedge clk) begin + case (quadrant) + 2'b00, + 2'b11: begin + x0 <= X_VALUE; + y0 <= 0; + z0 <= angle; + end + + 2'b01: begin + x0 <= 0; + y0 <= X_VALUE; + z0 <= {2'b00, angle[PHASE_DW-3:0]}; + end + + 2'b10: begin + x0 <= 0; + y0 <= -X_VALUE; + z0 <= {2'b11, angle[PHASE_DW-3:0]}; + end + endcase + end + + assign x_s[0] = x0; + assign y_s[0] = y0; + assign z_s[0] = z0; + assign data_in_d[0] = ddata_in; + + // cordic pipeline + + genvar i; + + generate + for (i=0; i < PHASE_DW-1; i=i+1) begin: rotation + ad_dds_cordic_pipe #( + .P_DW (PHASE_DW), + .D_DW (CORDIC_DW), + .DELAY_DW (DELAY_DW), + .SHIFT(i)) + pipe ( + .clk (clk), + .dataa_x (x_s[i]), + .dataa_y (y_s[i]), + .dataa_z (z_s[i]), + .datab_z (atan_table[i]), + .dir (z_s[i][PHASE_DW-1]), + .result_x (x_s[i+1]), + .result_y (y_s[i+1]), + .result_z (z_s[i+1]), + .data_delay_in (data_in_d[i]), + .data_delay_out (data_in_d[i+1]) + ); + end + endgenerate + + // x and y are cos(angle) and sin(angle) + + always @(posedge clk) begin + ddata_out <= data_in_d[PHASE_DW-1]; + sine <= y_s[PHASE_DW-1]; + cosine <= x_s[PHASE_DW-1]; + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_edge_detect.v b/src/adi/hdl/library/common/ad_edge_detect.v new file mode 100644 index 00000000..12f5ae2c --- /dev/null +++ b/src/adi/hdl/library/common/ad_edge_detect.v @@ -0,0 +1,83 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +// A simple edge detector circuit + +`timescale 1ns/100ps + +module ad_edge_detect #( + + parameter EDGE = 0) ( + + input clk, + input rst, + + input in, + output reg out); + + + localparam POS_EDGE = 0; + localparam NEG_EDGE = 1; + localparam ANY_EDGE = 2; + + reg ff_m1 = 0; + reg ff_m2 = 0; + + always @(posedge clk) begin + if (rst == 1) begin + ff_m1 <= 0; + ff_m2 <= 0; + end else begin + ff_m1 <= in; + ff_m2 <= ff_m1; + end + end + + always @(posedge clk) begin + if (rst == 1) begin + out <= 1'b0; + end else begin + if (EDGE == POS_EDGE) begin + out <= ff_m1 & ~ff_m2; + end else if (EDGE == NEG_EDGE) begin + out <= ~ff_m1 & ff_m2; + end else begin + out <= ff_m1 ^ ff_m2; + end + end + end + +endmodule + diff --git a/src/adi/hdl/library/common/ad_g2b.v b/src/adi/hdl/library/common/ad_g2b.v new file mode 100644 index 00000000..7d6ada66 --- /dev/null +++ b/src/adi/hdl/library/common/ad_g2b.v @@ -0,0 +1,59 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_g2b #( + + parameter DATA_WIDTH = 8) ( + + input [DATA_WIDTH-1:0] din, + output [DATA_WIDTH-1:0] dout); + + function [DATA_WIDTH-1:0] g2b; + input [DATA_WIDTH-1:0] g; + integer i; + begin + g2b[DATA_WIDTH-1] = g[DATA_WIDTH-1]; + for (i = DATA_WIDTH-1; i > 0; i = i -1) begin + g2b[i-1] = g2b[i] ^ g[i-1]; + end + end + endfunction + + assign dout = g2b(din); + +endmodule + diff --git a/src/adi/hdl/library/common/ad_iqcor.v b/src/adi/hdl/library/common/ad_iqcor.v new file mode 100644 index 00000000..cb1ae63d --- /dev/null +++ b/src/adi/hdl/library/common/ad_iqcor.v @@ -0,0 +1,183 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// iq correction = a*(i+x) + b*(q+y); offsets are added in dcfilter. +// if SCALE_ONLY is set to 1, b*(q+y) is set to 0, and the module is used for +// scale correction of channel I + +`timescale 1ns/100ps + +module ad_iqcor #( + + // select i/q if disabled + + parameter Q_OR_I_N = 0, + parameter SCALE_ONLY = 0, + parameter DISABLE = 0) ( + + // data interface + + input clk, + input valid, + input [15:0] data_in, + input [15:0] data_iq, + output valid_out, + output [15:0] data_out, + + // control interface + + input iqcor_enable, + input [15:0] iqcor_coeff_1, + input [15:0] iqcor_coeff_2); + + // internal registers + + reg p1_valid = 'd0; + reg [33:0] p1_data_p = 'd0; + reg valid_int = 'd0; + reg [15:0] data_int = 'd0; + reg [15:0] iqcor_coeff_1_r = 'd0; + reg [15:0] iqcor_coeff_2_r = 'd0; + + // internal signals + + wire [15:0] data_i_s; + wire [15:0] data_q_s; + wire [33:0] p1_data_p_i_s; + wire p1_valid_s; + wire [15:0] p1_data_i_s; + wire [33:0] p1_data_p_q_s; + wire [15:0] p1_data_q_s; + wire [15:0] p1_data_i_int; + wire [15:0] p1_data_q_int; + + // data-path disable + + generate + if (DISABLE == 1) begin + assign valid_out = valid; + assign data_out = data_in; + end else begin + assign valid_out = valid_int; + assign data_out = data_int; + end + endgenerate + + // swap i & q + + assign data_i_s = (Q_OR_I_N == 1 && SCALE_ONLY == 1'b0) ? data_iq : data_in; + assign data_q_s = (Q_OR_I_N == 1) ? data_in : data_iq; + + // coefficients are flopped to remove warnings from vivado + + always @(posedge clk) begin + iqcor_coeff_1_r <= iqcor_coeff_1; + iqcor_coeff_2_r <= iqcor_coeff_2; + end + + // scaling functions - i + + ad_mul #(.DELAY_DATA_WIDTH(17)) i_mul_i ( + .clk (clk), + .data_a ({data_i_s[15], data_i_s}), + .data_b ({iqcor_coeff_1_r[15], iqcor_coeff_1_r}), + .data_p (p1_data_p_i_s), + .ddata_in ({valid, data_i_s}), + .ddata_out ({p1_valid_s, p1_data_i_s})); + + generate + if (SCALE_ONLY == 0) begin + // scaling functions - q + + ad_mul #(.DELAY_DATA_WIDTH(16)) i_mul_q ( + .clk (clk), + .data_a ({data_q_s[15], data_q_s}), + .data_b ({iqcor_coeff_2_r[15], iqcor_coeff_2_r}), + .data_p (p1_data_p_q_s), + .ddata_in (data_q_s), + .ddata_out (p1_data_q_s)); + + // sum + end else begin + assign p1_data_p_q_s = 34'h0; + assign p1_data_q_s = 16'h0; + end + + endgenerate + generate + if (Q_OR_I_N == 1 && SCALE_ONLY == 0) begin + reg [15:0] p1_data_q = 'd0; + + always @(posedge clk) begin + p1_data_q <= p1_data_q_s; + end + + assign p1_data_i_int = 16'h0; + assign p1_data_q_int = p1_data_q; + + // sum + end else begin + reg [15:0] p1_data_i = 'd0; + + always @(posedge clk) begin + p1_data_i <= p1_data_i_s; + end + + assign p1_data_i_int = p1_data_i; + assign p1_data_q_int = 16'h0; + end + endgenerate + + always @(posedge clk) begin + p1_valid <= p1_valid_s; + p1_data_p <= p1_data_p_i_s + p1_data_p_q_s; + end + // output registers + + always @(posedge clk) begin + valid_int <= p1_valid; + if (iqcor_enable == 1'b1) begin + data_int <= p1_data_p[29:14]; + end else if (Q_OR_I_N == 1 && SCALE_ONLY == 0) begin + data_int <= p1_data_q_int; + end else begin + data_int <= p1_data_i_int; + end + end + + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_mem.v b/src/adi/hdl/library/common/ad_mem.v new file mode 100644 index 00000000..0843d4a1 --- /dev/null +++ b/src/adi/hdl/library/common/ad_mem.v @@ -0,0 +1,71 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_mem #( + + parameter DATA_WIDTH = 16, + parameter ADDRESS_WIDTH = 5) ( + + input clka, + input wea, + input [(ADDRESS_WIDTH-1):0] addra, + input [(DATA_WIDTH-1):0] dina, + + input clkb, + input reb, + input [(ADDRESS_WIDTH-1):0] addrb, + output reg [(DATA_WIDTH-1):0] doutb); + + (* ram_style = "block" *) + reg [(DATA_WIDTH-1):0] m_ram[0:((2**ADDRESS_WIDTH)-1)]; + + always @(posedge clka) begin + if (wea == 1'b1) begin + m_ram[addra] <= dina; + end + end + + always @(posedge clkb) begin + if (reb == 1'b1) begin + doutb <= m_ram[addrb]; + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_mem_asym.v b/src/adi/hdl/library/common/ad_mem_asym.v new file mode 100644 index 00000000..b4319690 --- /dev/null +++ b/src/adi/hdl/library/common/ad_mem_asym.v @@ -0,0 +1,148 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +// A simple asymetric memory. The write and read memory space must have the same size. +// 2^A_ADDRESS_WIDTH * A_DATA_WIDTH == 2^B_ADDRESS_WIDTH * B_DATA_WIDTH + +`timescale 1ns/100ps + +module ad_mem_asym #( + + parameter A_ADDRESS_WIDTH = 8, + parameter A_DATA_WIDTH = 256, + parameter B_ADDRESS_WIDTH = 10, + parameter B_DATA_WIDTH = 64) ( + + input clka, + input wea, + input [A_ADDRESS_WIDTH-1:0] addra, + input [A_DATA_WIDTH-1:0] dina, + + input clkb, + input reb, + input [B_ADDRESS_WIDTH-1:0] addrb, + output reg [B_DATA_WIDTH-1:0] doutb); + + + `define max(a,b) {(a) > (b) ? (a) : (b)} + `define min(a,b) {(a) < (b) ? (a) : (b)} + + function integer clog2; + input integer value; + begin + if (value < 2) + clog2 = value; + else begin + value = value - 1; + for (clog2 = 0; value > 0; clog2 = clog2 + 1) + value = value >> 1; + end + end + endfunction + + localparam MEM_ADDRESS_WIDTH = `max(A_ADDRESS_WIDTH, B_ADDRESS_WIDTH); + localparam MIN_WIDTH = `min(A_DATA_WIDTH, B_DATA_WIDTH); + localparam MAX_WIDTH = `max(A_DATA_WIDTH, B_DATA_WIDTH); + localparam MEM_DATA_WIDTH = MIN_WIDTH; + localparam MEM_SIZE = 2 ** MEM_ADDRESS_WIDTH; + localparam MEM_RATIO = MAX_WIDTH / MIN_WIDTH; + localparam MEM_RATIO_LOG2 = clog2(MEM_RATIO); + + // internal registers + + reg [MEM_DATA_WIDTH-1:0] m_ram[0:MEM_SIZE-1]; + + //--------------------------------------------------------------------------- + // write interface + //--------------------------------------------------------------------------- + + // write data width is narrower than read data width + generate if (A_DATA_WIDTH <= B_DATA_WIDTH) begin + always @(posedge clka) begin + if (wea == 1'b1) begin + m_ram[addra] <= dina; + end + end + end + endgenerate + + // write data width is wider than read data width + generate if (A_DATA_WIDTH > B_DATA_WIDTH) begin + always @(posedge clka) begin : memwrite + integer i; + reg [MEM_RATIO_LOG2-1:0] lsb; + for (i = 0; i < MEM_RATIO; i = i + 1) begin : awrite + lsb = i; + if (wea) begin + m_ram[{addra, lsb}] <= dina[i * MIN_WIDTH +: MIN_WIDTH]; + end + end + end + end + endgenerate + + //--------------------------------------------------------------------------- + // read interface + //--------------------------------------------------------------------------- + + // read data width is narrower than write data width + generate if (A_DATA_WIDTH >= B_DATA_WIDTH) begin + always @(posedge clkb) begin + if (reb == 1'b1) begin + doutb <= m_ram[addrb]; + end + end + end + endgenerate + + // read data width is wider than write data width + generate if (A_DATA_WIDTH < B_DATA_WIDTH) begin + always @(posedge clkb) begin : memread + integer i; + reg [MEM_RATIO_LOG2-1:0] lsb; + for (i = 0; i < MEM_RATIO; i = i + 1) begin : aread + lsb = i; + if (reb == 1'b1) begin + doutb[i*MIN_WIDTH +: MIN_WIDTH] <= m_ram[{addrb, lsb}]; + end + end + end + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_perfect_shuffle.v b/src/adi/hdl/library/common/ad_perfect_shuffle.v new file mode 100644 index 00000000..c0427651 --- /dev/null +++ b/src/adi/hdl/library/common/ad_perfect_shuffle.v @@ -0,0 +1,68 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// Each core or library found in this collection may have its own licensing terms. +// The user should keep this in in mind while exploring these cores. +// +// Redistribution and use in source and binary forms, +// with or without modification of this file, are permitted under the terms of either +// (at the option of the user): +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory, or at: +// https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +// +// OR +// +// 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +// https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_perfect_shuffle #( + parameter NUM_GROUPS = 2, + parameter WORDS_PER_GROUP = 2, + parameter WORD_WIDTH = 8 +) ( + input [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_in, + output [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_out +); + /* + * Performs the perfect shuffle operation. + * + * The perfect shuffle splits the input vector into NUM_GROUPS groups and then + * each group in WORDS_PER_GROUP. The output vector consists of WORDS_PER_GROUP + * groups and each group has NUM_GROUPS words. The data is remapped, so that + * the i-th word of the j-th word in the output vector is the j-th word of the + * i-th group of the input vector. + + * The inverse operation of the perfect shuffle is the perfect shuffle with + * both parameters swapped. + * I.e. [perfect_suffle B A [perfect_shuffle A B data]] == data + * + * Examples: + * NUM_GROUPS = 2, WORDS_PER_GROUP = 4 + * [A B C D a b c d] => [A a B b C c D d] + * NUM_GROUPS = 4, WORDS_PER_GROUP = 2 + * [A a B b C c D d] => [A B C D a b c d] + * NUM_GROUPS = 3, WORDS_PER_GROUP = 2 + * [A B a b 1 2] => [A a 1 B b 2] + */ + generate + genvar i; + genvar j; + for (i = 0; i < NUM_GROUPS; i = i + 1) begin: shuffle_outer + for (j = 0; j < WORDS_PER_GROUP; j = j + 1) begin: shuffle_inner + localparam src_lsb = (j + i * WORDS_PER_GROUP) * WORD_WIDTH; + localparam dst_lsb = (i + j * NUM_GROUPS) * WORD_WIDTH; + + assign data_out[dst_lsb+:WORD_WIDTH] = data_in[src_lsb+:WORD_WIDTH]; + end + end + endgenerate + +endmodule diff --git a/src/adi/hdl/library/common/ad_pnmon.v b/src/adi/hdl/library/common/ad_pnmon.v new file mode 100644 index 00000000..b6e52e75 --- /dev/null +++ b/src/adi/hdl/library/common/ad_pnmon.v @@ -0,0 +1,106 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// PN monitors + +`timescale 1ns/100ps + +module ad_pnmon #( + + parameter DATA_WIDTH = 16) ( + + // adc interface + + input adc_clk, + input adc_valid_in, + input [(DATA_WIDTH-1):0] adc_data_in, + input [(DATA_WIDTH-1):0] adc_data_pn, + + // pn out of sync and error + + output adc_pn_oos, + output adc_pn_err); + + // internal registers + + reg adc_valid_d = 'd0; + reg adc_pn_match_d = 'd0; + reg adc_pn_match_z = 'd0; + reg adc_pn_oos_int = 'd0; + reg adc_pn_err_int = 'd0; + reg [ 3:0] adc_pn_oos_count = 'd0; + + // internal signals + + wire adc_pn_match_d_s; + wire adc_pn_match_z_s; + wire adc_pn_match_s; + wire adc_pn_update_s; + wire adc_pn_err_s; + + // make sure data is not 0, sequence will fail. + + assign adc_pn_match_d_s = (adc_data_in == adc_data_pn) ? 1'b1 : 1'b0; + assign adc_pn_match_z_s = (adc_data_in == 'd0) ? 1'b0 : 1'b1; + assign adc_pn_match_s = adc_pn_match_d & adc_pn_match_z; + assign adc_pn_update_s = ~(adc_pn_oos_int ^ adc_pn_match_s); + assign adc_pn_err_s = ~(adc_pn_oos_int | adc_pn_match_s); + + // pn oos and counters (16 to clear and set). + + assign adc_pn_oos = adc_pn_oos_int; + assign adc_pn_err = adc_pn_err_int; + + always @(posedge adc_clk) begin + adc_valid_d <= adc_valid_in; + adc_pn_match_d <= adc_pn_match_d_s; + adc_pn_match_z <= adc_pn_match_z_s; + if (adc_valid_d == 1'b1) begin + adc_pn_err_int <= adc_pn_err_s; + if ((adc_pn_update_s == 1'b1) && (adc_pn_oos_count >= 15)) begin + adc_pn_oos_int <= ~adc_pn_oos_int; + end + if (adc_pn_update_s == 1'b1) begin + adc_pn_oos_count <= adc_pn_oos_count + 1'b1; + end else begin + adc_pn_oos_count <= 'd0; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** + diff --git a/src/adi/hdl/library/common/ad_pps_receiver.v b/src/adi/hdl/library/common/ad_pps_receiver.v new file mode 100644 index 00000000..7a9c1b28 --- /dev/null +++ b/src/adi/hdl/library/common/ad_pps_receiver.v @@ -0,0 +1,130 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +`timescale 1ns/1ps + +module ad_pps_receiver ( + input clk, + input rst, + input gps_pps, + + input up_clk, + input up_rstn, + output reg [31:0] up_pps_rcounter, + output reg up_pps_status, + input up_irq_mask, + output reg up_irq); + + // ************************************************************************* + // 1PPS reception and reporting counter implementation + // Note: this module should run on the core clock + // ************************************************************************* + + reg [ 2:0] gps_pps_m = 3'b0; + reg [ 2:0] up_pps_m = 3'b0; + reg up_pps_status_m = 1'b0; + reg pps_toggle = 1'b0; + reg [31:0] free_rcounter = 32'b0; + reg [31:0] pps_rcounter = 32'b0; + reg pps_status = 1'b0; + + wire pps_posedge_s; + wire up_pps_posedge_s; + + // gps_pps is asynchronous from the clk + + always @(posedge clk) begin + if (rst == 1'b1) begin + gps_pps_m <= 3'b0; + end else begin + gps_pps_m <= {gps_pps_m[1:0], gps_pps}; + end + end + assign pps_posedge_s = ~gps_pps_m[2] & gps_pps_m[1]; + + always @(posedge clk) begin + if (rst == 1'b1) begin + free_rcounter <= 32'b0; + pps_rcounter <= 32'b0; + pps_status <= 1'b1; + end else if (pps_posedge_s == 1'b1) begin + free_rcounter <= 32'b0; + pps_rcounter <= free_rcounter; + pps_status <= 1'b0; + end else begin + free_rcounter <= free_rcounter + 32'b1; + if (free_rcounter[28] == 1'b1) begin + pps_status <= 1'b1; + end + end + end + + // up_tdd_pps_rcounter CDC + + always @(posedge clk) begin + if (rst == 1'b1) begin + pps_toggle <= 1'b0; + end else if (pps_posedge_s == 1'b1) begin + pps_toggle <= ~pps_toggle; + end + end + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_pps_m <= 3'b0; + up_pps_rcounter <= 1'b0; + up_pps_status_m <= 1'b1; + up_pps_status <= 1'b1; + end else begin + up_pps_m <= {up_pps_m[1:0], pps_toggle}; + up_pps_status_m <= pps_status; + up_pps_status <= up_pps_status_m; + if ((up_pps_m[2] ^ up_pps_m[1]) == 1'b1) begin + up_pps_rcounter <= pps_rcounter; + end + end + end + assign up_pps_posedge_s = ~up_pps_m[2] & up_pps_m[1]; + + // IRQ generation + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_irq <= 1'b0; + end else begin + up_irq <= up_pps_posedge_s & ~up_irq_mask; + end + end + +endmodule diff --git a/src/adi/hdl/library/common/ad_pps_receiver_constr.ttcl b/src/adi/hdl/library/common/ad_pps_receiver_constr.ttcl new file mode 100644 index 00000000..5ed2c38a --- /dev/null +++ b/src/adi/hdl/library/common/ad_pps_receiver_constr.ttcl @@ -0,0 +1,20 @@ +<: set ComponentName [getComponentNameString] :> +<: setOutputDirectory "./" :> +<: setFileName [ttcl_add $ComponentName "_pps_constr"] :> +<: setFileExtension ".xdc" :> +<: setFileProcessingOrder late :> +<: set pps_enable [getBooleanValue "PPS_RECEIVER_ENABLE"] :> + +<: if {$pps_enable} { :> + + set_property ASYNC_REG TRUE \ + [get_cells -hier *_pps_m*] \ + [get_cells -hier *_pps_status_m*] + + set_false_path -to [get_cells -hier -filter {name =~ *_pps_m_reg[0] && IS_SEQUENTIAL}] + set_false_path -from [get_cells -hier -filter {name =~ *pps_status_reg && IS_SEQUENTIAL}] \ + -to [get_cells -hier -filter {name =~ *up_pps_status_m_reg && IS_SEQUENTIAL}] + set_false_path -to [get_cells -hier -filter {name =~ *up_pps_rcounter_reg* && IS_SEQUENTIAL}] + +<: } :> + diff --git a/src/adi/hdl/library/common/ad_rst.v b/src/adi/hdl/library/common/ad_rst.v new file mode 100644 index 00000000..43109633 --- /dev/null +++ b/src/adi/hdl/library/common/ad_rst.v @@ -0,0 +1,77 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_rst ( + + // clock reset + + input rst_async, + input clk, + output rstn, + output reg rst); + + // internal registers + reg rst_async_d1 = 1'd1; + reg rst_async_d2 = 1'd1; + reg rst_sync = 1'd1; + reg rst_sync_d = 1'd1; + + // simple reset synchronizer + always @(posedge clk or posedge rst_async) begin + if (rst_async) begin + rst_async_d1 <= 1'b1; + rst_async_d2 <= 1'b1; + rst_sync <= 1'b1; + end else begin + rst_async_d1 <= 1'b0; + rst_async_d2 <= rst_async_d1; + rst_sync <= rst_async_d2; + end + end + + // two-stage synchronizer to prevent metastability on the falling edge + always @(posedge clk) begin + rst_sync_d <= rst_sync; + rst <= rst_sync_d; + end + + assign rstn = ~rst; + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_ss_422to444.v b/src/adi/hdl/library/common/ad_ss_422to444.v new file mode 100644 index 00000000..d408d910 --- /dev/null +++ b/src/adi/hdl/library/common/ad_ss_422to444.v @@ -0,0 +1,138 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Input must be RGB or CrYCb in that order, output is CrY/CbY + +`timescale 1ns/100ps + +module ad_ss_422to444 #( + + parameter CR_CB_N = 0, + parameter DELAY_DATA_WIDTH = 16) ( + + // 422 inputs + + input clk, + input s422_de, + input [DW:0] s422_sync, + input [15:0] s422_data, + + // 444 outputs + + output reg [DW:0] s444_sync, + output reg [23:0] s444_data); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // internal registers + + reg cr_cb_sel = 'd0; + reg s422_de_d = 'd0; + reg [DW:0] s422_sync_d = 'd0; + reg s422_de_2d = 'd0; + reg [7:0] s422_Y_d; + reg [7:0] s422_CbCr_d; + reg [7:0] s422_CbCr_2d; + reg [ 8:0] s422_CbCr_avg; + + // internal wires + + wire [ 7:0] s422_Y; + wire [ 7:0] s422_CbCr; + + // Input format is + // [15:8] Cb/Cr + // [ 7:0] Y + // + // Output format is + // [23:15] Cr + // [16: 8] Y + // [ 7: 0] Cb + + assign s422_Y = s422_data[7:0]; + assign s422_CbCr = s422_data[15:8]; + + // first data on de assertion is cb (0x0), then cr (0x1). + // previous data is held when not current + + always @(posedge clk) begin + if (s422_de_d == 1'b1) begin + cr_cb_sel <= ~cr_cb_sel; + end else begin + cr_cb_sel <= CR_CB_N; + end + end + + // pipe line stages + + always @(posedge clk) begin + s422_de_d <= s422_de; + s422_sync_d <= s422_sync; + s422_de_2d <= s422_de_d; + s422_Y_d <= s422_Y; + + s422_CbCr_d <= s422_CbCr; + s422_CbCr_2d <= s422_CbCr_d; + end + + // If both the left and the right sample are valid do the average, otherwise + // use the only valid. + always @(s422_de_2d, s422_de, s422_CbCr, s422_CbCr_2d) + begin + if (s422_de == 1'b1 && s422_de_2d) + s422_CbCr_avg <= s422_CbCr + s422_CbCr_2d; + else if (s422_de == 1'b1) + s422_CbCr_avg <= {s422_CbCr, 1'b0}; + else + s422_CbCr_avg <= {s422_CbCr_2d, 1'b0}; + end + + // 444 outputs + + always @(posedge clk) begin + s444_sync <= s422_sync_d; + s444_data[15:8] <= s422_Y_d; + if (cr_cb_sel) begin + s444_data[23:16] <= s422_CbCr_d; + s444_data[ 7: 0] <= s422_CbCr_avg[8:1]; + end else begin + s444_data[23:16] <= s422_CbCr_avg[8:1]; + s444_data[ 7: 0] <= s422_CbCr_d; + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_ss_444to422.v b/src/adi/hdl/library/common/ad_ss_444to422.v new file mode 100644 index 00000000..542de95a --- /dev/null +++ b/src/adi/hdl/library/common/ad_ss_444to422.v @@ -0,0 +1,134 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// Input must be RGB or CrYCb in that order, output is CrY/CbY + +`timescale 1ns/100ps + +module ad_ss_444to422 #( + + parameter CR_CB_N = 0, + parameter DELAY_DATA_WIDTH = 16) ( + + // 444 inputs + + input clk, + input s444_de, + input [DW:0] s444_sync, + input [23:0] s444_data, + + // 422 outputs + + output reg [DW:0] s422_sync, + output reg [15:0] s422_data); + + localparam DW = DELAY_DATA_WIDTH - 1; + + // internal registers + + reg s444_de_d = 'd0; + reg [DW:0] s444_sync_d = 'd0; + reg [23:0] s444_data_d = 'd0; + reg s444_de_2d = 'd0; + reg [DW:0] s444_sync_2d = 'd0; + reg [23:0] s444_data_2d = 'd0; + reg s444_de_3d = 'd0; + reg [DW:0] s444_sync_3d = 'd0; + reg [23:0] s444_data_3d = 'd0; + reg [ 7:0] cr = 'd0; + reg [ 7:0] cb = 'd0; + reg cr_cb_sel = 'd0; + + // internal wires + + wire [ 9:0] cr_s; + wire [ 9:0] cb_s; + + // fill the data pipe lines, hold the last data on edges + + always @(posedge clk) begin + s444_de_d <= s444_de; + s444_sync_d <= s444_sync; + if (s444_de == 1'b1) begin + s444_data_d <= s444_data; + end + s444_de_2d <= s444_de_d; + s444_sync_2d <= s444_sync_d; + if (s444_de_d == 1'b1) begin + s444_data_2d <= s444_data_d; + end + s444_de_3d <= s444_de_2d; + s444_sync_3d <= s444_sync_2d; + if (s444_de_2d == 1'b1) begin + s444_data_3d <= s444_data_2d; + end + end + + // get the average 0.25*s(n-1) + 0.5*s(n) + 0.25*s(n+1) + + assign cr_s = {2'd0, s444_data_d[23:16]} + + {2'd0, s444_data_3d[23:16]} + + {1'd0, s444_data_2d[23:16], 1'd0}; + + assign cb_s = {2'd0, s444_data_d[7:0]} + + {2'd0, s444_data_3d[7:0]} + + {1'd0, s444_data_2d[7:0], 1'd0}; + + always @(posedge clk) begin + cr <= cr_s[9:2]; + cb <= cb_s[9:2]; + if (s444_de_3d == 1'b1) begin + cr_cb_sel <= ~cr_cb_sel; + end else begin + cr_cb_sel <= CR_CB_N; + end + end + + // 422 outputs + + always @(posedge clk) begin + s422_sync <= s444_sync_3d; + if (s444_de_3d == 1'b0) begin + s422_data <= 'd0; + end else if (cr_cb_sel == 1'b1) begin + s422_data <= {cr, s444_data_3d[15:8]}; + end else begin + s422_data <= {cb, s444_data_3d[15:8]}; + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/ad_sysref_gen.v b/src/adi/hdl/library/common/ad_sysref_gen.v new file mode 100644 index 00000000..1b255eab --- /dev/null +++ b/src/adi/hdl/library/common/ad_sysref_gen.v @@ -0,0 +1,85 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_sysref_gen ( + + input core_clk, + + input sysref_en, + output reg sysref_out +); + + // SYSREF period is multiple of core_clk, and has a duty cycle of 50% + // NOTE: if SYSREF always on (this is a JESD204 IP configuration), + // the period must be a correct multiple of the multiframe period + parameter SYSREF_PERIOD = 128; + + localparam SYSREF_HALFPERIOD = SYSREF_PERIOD/2 - 1; + + reg [ 7:0] counter; + reg sysref_en_m1; + reg sysref_en_m2; + reg sysref_en_int; + + // bring the enable signal to JESD core clock domain + always @(posedge core_clk) begin + sysref_en_m1 <= sysref_en; + sysref_en_m2 <= sysref_en_m1; + sysref_en_int <= sysref_en_m2; + end + + // free running counter for periodic SYSREF generation + always @(posedge core_clk) begin + if (sysref_en_int) begin + counter <= (counter < SYSREF_HALFPERIOD) ? counter + 1'b1 : 8'h0; + end else begin + counter <= 8'h0; + end + end + + // generate SYSREF + always @(posedge core_clk) begin + if (sysref_en_int) begin + if (counter == SYSREF_HALFPERIOD) begin + sysref_out <= ~sysref_out; + end + end else begin + sysref_out <= 1'b0; + end + end + +endmodule diff --git a/src/adi/hdl/library/common/ad_tdd_control.v b/src/adi/hdl/library/common/ad_tdd_control.v new file mode 100644 index 00000000..31658982 --- /dev/null +++ b/src/adi/hdl/library/common/ad_tdd_control.v @@ -0,0 +1,834 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/1ps + +module ad_tdd_control#( + + parameter integer TX_DATA_PATH_DELAY = 0, + parameter integer CONTROL_PATH_DELAY = 0) ( + + // clock and reset + + input clk, + input rst, + + // TDD timing signals + + input tdd_enable, + input tdd_secondary, + input tdd_tx_only, + input tdd_rx_only, + input [ 7:0] tdd_burst_count, + input [23:0] tdd_counter_init, + input [23:0] tdd_frame_length, + input [23:0] tdd_vco_rx_on_1, + input [23:0] tdd_vco_rx_off_1, + input [23:0] tdd_vco_tx_on_1, + input [23:0] tdd_vco_tx_off_1, + input [23:0] tdd_rx_on_1, + input [23:0] tdd_rx_off_1, + input [23:0] tdd_rx_dp_on_1, + input [23:0] tdd_rx_dp_off_1, + input [23:0] tdd_tx_on_1, + input [23:0] tdd_tx_off_1, + input [23:0] tdd_tx_dp_on_1, + input [23:0] tdd_tx_dp_off_1, + input [23:0] tdd_vco_rx_on_2, + input [23:0] tdd_vco_rx_off_2, + input [23:0] tdd_vco_tx_on_2, + input [23:0] tdd_vco_tx_off_2, + input [23:0] tdd_rx_on_2, + input [23:0] tdd_rx_off_2, + input [23:0] tdd_rx_dp_on_2, + input [23:0] tdd_rx_dp_off_2, + input [23:0] tdd_tx_on_2, + input [23:0] tdd_tx_off_2, + input [23:0] tdd_tx_dp_on_2, + input [23:0] tdd_tx_dp_off_2, + input tdd_sync, + + // TDD control signals + + output reg tdd_tx_dp_en, + output reg tdd_rx_dp_en, + output reg tdd_rx_vco_en, + output reg tdd_tx_vco_en, + output reg tdd_rx_rf_en, + output reg tdd_tx_rf_en, + + output [23:0] tdd_counter_status); + + + localparam ON = 1; + localparam OFF = 0; + + // tdd control related + + // tdd counter related + + reg [23:0] tdd_counter = 24'h0; + reg [ 5:0] tdd_burst_counter = 6'h0; + + reg tdd_cstate = OFF; + reg tdd_cstate_next = OFF; + + reg counter_at_tdd_vco_rx_on_1 = 1'b0; + reg counter_at_tdd_vco_rx_off_1 = 1'b0; + reg counter_at_tdd_vco_tx_on_1 = 1'b0; + reg counter_at_tdd_vco_tx_off_1 = 1'b0; + reg counter_at_tdd_rx_on_1 = 1'b0; + reg counter_at_tdd_rx_off_1 = 1'b0; + reg counter_at_tdd_rx_dp_on_1 = 1'b0; + reg counter_at_tdd_rx_dp_off_1 = 1'b0; + reg counter_at_tdd_tx_on_1 = 1'b0; + reg counter_at_tdd_tx_off_1 = 1'b0; + reg counter_at_tdd_tx_dp_on_1 = 1'b0; + reg counter_at_tdd_tx_dp_off_1 = 1'b0; + reg counter_at_tdd_vco_rx_on_2 = 1'b0; + reg counter_at_tdd_vco_rx_off_2 = 1'b0; + reg counter_at_tdd_vco_tx_on_2 = 1'b0; + reg counter_at_tdd_vco_tx_off_2 = 1'b0; + reg counter_at_tdd_rx_on_2 = 1'b0; + reg counter_at_tdd_rx_off_2 = 1'b0; + reg counter_at_tdd_rx_dp_on_2 = 1'b0; + reg counter_at_tdd_rx_dp_off_2 = 1'b0; + reg counter_at_tdd_tx_on_2 = 1'b0; + reg counter_at_tdd_tx_off_2 = 1'b0; + reg counter_at_tdd_tx_dp_on_2 = 1'b0; + reg counter_at_tdd_tx_dp_off_2 = 1'b0; + + reg tdd_last_burst = 1'b0; + + reg tdd_sync_d1 = 1'b0; + reg tdd_sync_d2 = 1'b0; + reg tdd_sync_d3 = 1'b0; + + reg tdd_endof_frame = 1'b0; + + // internal signals + + wire [23:0] tdd_vco_rx_on_1_s; + wire [23:0] tdd_vco_rx_off_1_s; + wire [23:0] tdd_vco_tx_on_1_s; + wire [23:0] tdd_vco_tx_off_1_s; + wire [23:0] tdd_rx_on_1_s; + wire [23:0] tdd_rx_off_1_s; + wire [23:0] tdd_tx_on_1_s; + wire [23:0] tdd_tx_off_1_s; + wire [23:0] tdd_tx_dp_on_1_s; + wire [23:0] tdd_tx_dp_off_1_s; + + wire [23:0] tdd_vco_rx_on_2_s; + wire [23:0] tdd_vco_rx_off_2_s; + wire [23:0] tdd_vco_tx_on_2_s; + wire [23:0] tdd_vco_tx_off_2_s; + wire [23:0] tdd_rx_on_2_s; + wire [23:0] tdd_rx_off_2_s; + wire [23:0] tdd_tx_on_2_s; + wire [23:0] tdd_tx_off_2_s; + wire [23:0] tdd_tx_dp_on_2_s; + wire [23:0] tdd_tx_dp_off_2_s; + wire tdd_endof_burst; + wire tdd_txrx_only_en_s; + + assign tdd_counter_status = tdd_counter; + + // synchronization of tdd_sync + always @(posedge clk) begin + if (rst == 1'b1) begin + tdd_sync_d1 <= 1'b0; + tdd_sync_d2 <= 1'b0; + tdd_sync_d3 <= 1'b0; + end else begin + tdd_sync_d1 <= tdd_sync; + tdd_sync_d2 <= tdd_sync_d1; + tdd_sync_d3 <= tdd_sync_d2; + end + end + + // *************************************************************************** + // tdd counter (state machine) + // *************************************************************************** + + always @(posedge clk) begin + if (rst == 1'b1) begin + tdd_cstate <= OFF; + end else begin + tdd_cstate <= tdd_cstate_next; + end + end + + always @* begin + tdd_cstate_next <= tdd_cstate; + + case (tdd_cstate) + ON : begin + if ((tdd_enable == 1'b0) || (tdd_endof_burst == 1'b1)) begin + tdd_cstate_next <= OFF; + end + end + + OFF : begin + if(tdd_enable == 1'b1) begin + tdd_cstate_next <= ((~tdd_sync_d3 & tdd_sync_d2) == 1'b1) ? ON : OFF; + end + end + endcase + end + + always @(posedge clk) begin + if (tdd_counter == (tdd_frame_length - 1'b1)) begin + tdd_endof_frame <= 1'b1; + end else begin + tdd_endof_frame <= 1'b0; + end + end + assign tdd_endof_burst = ((tdd_last_burst == 1'b1) && (tdd_endof_frame == 1'b1)) ? 1'b1 : 1'b0; + + // tdd free running counter + always @(posedge clk) begin + if (rst == 1'b1) begin + tdd_counter <= tdd_counter_init; + end else begin + if (tdd_cstate == ON) begin + if ((~tdd_sync_d3 & tdd_sync_d2) == 1'b1) begin + tdd_counter <= 24'b0; + end else begin + tdd_counter <= (tdd_endof_frame == 1'b1) ? 24'b0 : tdd_counter + 1'b1; + end + end else begin + tdd_counter <= tdd_counter_init; + end + end + end + + // tdd burst counter + always @(posedge clk) begin + if (tdd_cstate == OFF) begin + tdd_burst_counter <= tdd_burst_count; + end else if ((tdd_burst_counter != 0) && (tdd_endof_frame == 1'b1)) begin + tdd_burst_counter <= tdd_burst_counter - 1'b1; + end + end + + always @(posedge clk) begin + tdd_last_burst <= (tdd_burst_counter == 6'b1) ? 1'b1 : 1'b0; + end + + // *************************************************************************** + // generate control signals + // *************************************************************************** + + // start/stop rx vco + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_rx_on_1 <= 1'b0; + end else if(tdd_counter == tdd_vco_rx_on_1_s) begin + counter_at_tdd_vco_rx_on_1 <= 1'b1; + end else begin + counter_at_tdd_vco_rx_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_rx_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_vco_rx_on_2_s)) begin + counter_at_tdd_vco_rx_on_2 <= 1'b1; + end else begin + counter_at_tdd_vco_rx_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_rx_off_1 <= 1'b0; + end else if(tdd_counter == tdd_vco_rx_off_1_s) begin + counter_at_tdd_vco_rx_off_1 <= 1'b1; + end else begin + counter_at_tdd_vco_rx_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_rx_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_vco_rx_off_2_s)) begin + counter_at_tdd_vco_rx_off_2 <= 1'b1; + end else begin + counter_at_tdd_vco_rx_off_2 <= 1'b0; + end + end + + // start/stop tx vco + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_tx_on_1 <= 1'b0; + end else if(tdd_counter == tdd_vco_tx_on_1_s) begin + counter_at_tdd_vco_tx_on_1 <= 1'b1; + end else begin + counter_at_tdd_vco_tx_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_tx_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_vco_tx_on_2_s)) begin + counter_at_tdd_vco_tx_on_2 <= 1'b1; + end else begin + counter_at_tdd_vco_tx_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_tx_off_1 <= 1'b0; + end else if(tdd_counter == tdd_vco_tx_off_1_s) begin + counter_at_tdd_vco_tx_off_1 <= 1'b1; + end else begin + counter_at_tdd_vco_tx_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_vco_tx_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_vco_tx_off_2_s)) begin + counter_at_tdd_vco_tx_off_2 <= 1'b1; + end else begin + counter_at_tdd_vco_tx_off_2 <= 1'b0; + end + end + + // start/stop rx rf path + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_on_1 <= 1'b0; + end else if(tdd_counter == tdd_rx_on_1_s) begin + counter_at_tdd_rx_on_1 <= 1'b1; + end else begin + counter_at_tdd_rx_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_rx_on_2_s)) begin + counter_at_tdd_rx_on_2 <= 1'b1; + end else begin + counter_at_tdd_rx_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_off_1 <= 1'b0; + end else if(tdd_counter == tdd_rx_off_1_s) begin + counter_at_tdd_rx_off_1 <= 1'b1; + end else begin + counter_at_tdd_rx_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_rx_off_2_s)) begin + counter_at_tdd_rx_off_2 <= 1'b1; + end else begin + counter_at_tdd_rx_off_2 <= 1'b0; + end + end + + // start/stop tx rf path + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_on_1 <= 1'b0; + end else if(tdd_counter == tdd_tx_on_1_s) begin + counter_at_tdd_tx_on_1 <= 1'b1; + end else begin + counter_at_tdd_tx_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_tx_on_2_s)) begin + counter_at_tdd_tx_on_2 <= 1'b1; + end else begin + counter_at_tdd_tx_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_off_1 <= 1'b0; + end else if(tdd_counter == tdd_tx_off_1_s) begin + counter_at_tdd_tx_off_1 <= 1'b1; + end else begin + counter_at_tdd_tx_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_tx_off_2_s)) begin + counter_at_tdd_tx_off_2 <= 1'b1; + end else begin + counter_at_tdd_tx_off_2 <= 1'b0; + end + end + + // start/stop tx data path + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_dp_on_1 <= 1'b0; + end else if(tdd_counter == tdd_tx_dp_on_1_s) begin + counter_at_tdd_tx_dp_on_1 <= 1'b1; + end else begin + counter_at_tdd_tx_dp_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_dp_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_tx_dp_on_2_s)) begin + counter_at_tdd_tx_dp_on_2 <= 1'b1; + end else begin + counter_at_tdd_tx_dp_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_dp_off_1 <= 1'b0; + end else if(tdd_counter == tdd_tx_dp_off_1_s) begin + counter_at_tdd_tx_dp_off_1 <= 1'b1; + end else begin + counter_at_tdd_tx_dp_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_tx_dp_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_tx_dp_off_2_s)) begin + counter_at_tdd_tx_dp_off_2 <= 1'b1; + end else begin + counter_at_tdd_tx_dp_off_2 <= 1'b0; + end + end + + // start/stop rx data path + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_dp_on_1 <= 1'b0; + end else if(tdd_counter == tdd_rx_dp_on_1) begin + counter_at_tdd_rx_dp_on_1 <= 1'b1; + end else begin + counter_at_tdd_rx_dp_on_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_dp_on_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_rx_dp_on_2)) begin + counter_at_tdd_rx_dp_on_2 <= 1'b1; + end else begin + counter_at_tdd_rx_dp_on_2 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_dp_off_1 <= 1'b0; + end else if(tdd_counter == tdd_rx_dp_off_1) begin + counter_at_tdd_rx_dp_off_1 <= 1'b1; + end else begin + counter_at_tdd_rx_dp_off_1 <= 1'b0; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + counter_at_tdd_rx_dp_off_2 <= 1'b0; + end else if((tdd_secondary == 1'b1) && (tdd_counter == tdd_rx_dp_off_2)) begin + counter_at_tdd_rx_dp_off_2 <= 1'b1; + end else begin + counter_at_tdd_rx_dp_off_2 <= 1'b0; + end + end + + // control-path delay compensation + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_rx_on_1_comp ( + .clk(clk), + .A(tdd_vco_rx_on_1), + .Amax(tdd_frame_length), + .out(tdd_vco_rx_on_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_rx_off_1_comp ( + .clk(clk), + .A(tdd_vco_rx_off_1), + .Amax(tdd_frame_length), + .out(tdd_vco_rx_off_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_tx_on_1_comp ( + .clk(clk), + .A(tdd_vco_tx_on_1), + .Amax(tdd_frame_length), + .out(tdd_vco_tx_on_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_tx_off_1_comp ( + .clk(clk), + .A(tdd_vco_tx_off_1), + .Amax(tdd_frame_length), + .out(tdd_vco_tx_off_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_rx_on_1_comp ( + .clk(clk), + .A(tdd_rx_on_1), + .Amax(tdd_frame_length), + .out(tdd_rx_on_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_rx_off_1_comp ( + .clk(clk), + .A(tdd_rx_off_1), + .Amax(tdd_frame_length), + .out(tdd_rx_off_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_on_1_comp ( + .clk(clk), + .A(tdd_tx_on_1), + .Amax(tdd_frame_length), + .out(tdd_tx_on_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_off_1_comp ( + .clk(clk), + .A(tdd_tx_off_1), + .Amax(tdd_frame_length), + .out(tdd_tx_off_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_rx_on_2_comp ( + .clk(clk), + .A(tdd_vco_rx_on_2), + .Amax(tdd_frame_length), + .out(tdd_vco_rx_on_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_rx_off_2_comp ( + .clk(clk), + .A(tdd_vco_rx_off_2), + .Amax(tdd_frame_length), + .out(tdd_vco_rx_off_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_tx_on_2_comp ( + .clk(clk), + .A(tdd_vco_tx_on_2), + .Amax(tdd_frame_length), + .out(tdd_vco_tx_on_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_vco_tx_off_2_comp ( + .clk(clk), + .A(tdd_vco_tx_off_2), + .Amax(tdd_frame_length), + .out(tdd_vco_tx_off_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_rx_on_2_comp ( + .clk(clk), + .A(tdd_rx_on_2), + .Amax(tdd_frame_length), + .out(tdd_rx_on_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_rx_off_2_comp ( + .clk(clk), + .A(tdd_rx_off_2), + .Amax(tdd_frame_length), + .out(tdd_rx_off_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_on_2_comp ( + .clk(clk), + .A(tdd_tx_on_2), + .Amax(tdd_frame_length), + .out(tdd_tx_on_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(CONTROL_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_off_2_comp ( + .clk(clk), + .A(tdd_tx_off_2), + .Amax(tdd_frame_length), + .out(tdd_tx_off_2_s), + .CE(1'b1) + ); + + // internal data-path delay compensation + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(TX_DATA_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_dp_on_1_comp ( + .clk(clk), + .A(tdd_tx_dp_on_1), + .Amax(tdd_frame_length), + .out(tdd_tx_dp_on_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(TX_DATA_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_dp_on_2_comp ( + .clk(clk), + .A(tdd_tx_dp_on_2), + .Amax(tdd_frame_length), + .out(tdd_tx_dp_on_2_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(TX_DATA_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_dp_off_1_comp ( + .clk(clk), + .A(tdd_tx_dp_off_1), + .Amax(tdd_frame_length), + .out(tdd_tx_dp_off_1_s), + .CE(1'b1) + ); + + ad_addsub #( + .A_DATA_WIDTH(24), + .B_DATA_VALUE(TX_DATA_PATH_DELAY), + .ADD_OR_SUB_N(0) + ) i_tx_dp_off_2_comp ( + .clk(clk), + .A(tdd_tx_dp_off_2), + .Amax(tdd_frame_length), + .out(tdd_tx_dp_off_2_s), + .CE(1'b1) + ); + + // output logic + + assign tdd_txrx_only_en_s = tdd_tx_only ^ tdd_rx_only; + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_rx_vco_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_vco_rx_off_1 == 1'b1) || (counter_at_tdd_vco_rx_off_2 == 1'b1)) begin + tdd_rx_vco_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_vco_rx_on_1 == 1'b1) || (counter_at_tdd_vco_rx_on_2 == 1'b1))) begin + tdd_rx_vco_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_rx_vco_en <= tdd_rx_only; + end else begin + tdd_rx_vco_en <= tdd_rx_vco_en; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_tx_vco_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_vco_tx_off_1 == 1'b1) || (counter_at_tdd_vco_tx_off_2 == 1'b1)) begin + tdd_tx_vco_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_vco_tx_on_1 == 1'b1) || (counter_at_tdd_vco_tx_on_2 == 1'b1))) begin + tdd_tx_vco_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_tx_vco_en <= tdd_tx_only; + end else begin + tdd_tx_vco_en <= tdd_tx_vco_en; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_rx_rf_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_rx_off_1 == 1'b1) || (counter_at_tdd_rx_off_2 == 1'b1)) begin + tdd_rx_rf_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_rx_on_1 == 1'b1) || (counter_at_tdd_rx_on_2 == 1'b1))) begin + tdd_rx_rf_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_rx_rf_en <= tdd_rx_only; + end else begin + tdd_rx_rf_en <= tdd_rx_rf_en; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_tx_rf_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_tx_off_1 == 1'b1) || (counter_at_tdd_tx_off_2 == 1'b1)) begin + tdd_tx_rf_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_tx_on_1 == 1'b1) || (counter_at_tdd_tx_on_2 == 1'b1))) begin + tdd_tx_rf_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_tx_rf_en <= tdd_tx_only; + end else begin + tdd_tx_rf_en <= tdd_tx_rf_en; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_tx_dp_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_tx_dp_off_1 == 1'b1) || (counter_at_tdd_tx_dp_off_2 == 1'b1)) begin + tdd_tx_dp_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_tx_dp_on_1 == 1'b1) || (counter_at_tdd_tx_dp_on_2 == 1'b1))) begin + tdd_tx_dp_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_tx_dp_en <= tdd_tx_only; + end else begin + tdd_tx_dp_en <= tdd_tx_dp_en; + end + end + + always @(posedge clk) begin + if(rst == 1'b1) begin + tdd_rx_dp_en <= 1'b0; + end else if((tdd_cstate == OFF) || (counter_at_tdd_rx_dp_off_1 == 1'b1) || (counter_at_tdd_rx_dp_off_2 == 1'b1)) begin + tdd_rx_dp_en <= 1'b0; + end else if((tdd_cstate == ON) && ((counter_at_tdd_rx_dp_on_1 == 1'b1) || (counter_at_tdd_rx_dp_on_2 == 1'b1))) begin + tdd_rx_dp_en <= 1'b1; + end else if((tdd_cstate == ON) && (tdd_txrx_only_en_s == 1'b1)) begin + tdd_rx_dp_en <= tdd_rx_only; + end else begin + tdd_rx_dp_en <= tdd_rx_dp_en; + end + end + +endmodule + diff --git a/src/adi/hdl/library/common/ad_xcvr_rx_if.v b/src/adi/hdl/library/common/ad_xcvr_rx_if.v new file mode 100644 index 00000000..614ab001 --- /dev/null +++ b/src/adi/hdl/library/common/ad_xcvr_rx_if.v @@ -0,0 +1,80 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_xcvr_rx_if ( + + // jesd interface + + input rx_clk, + input [ 3:0] rx_ip_sof, + input [31:0] rx_ip_data, + output reg rx_sof, + output reg [31:0] rx_data); + + + // internal registers + + reg [31:0] rx_ip_data_d = 'd0; + reg [ 3:0] rx_ip_sof_hold = 'd0; + reg [ 3:0] rx_ip_sof_d = 'd0; + + // dword may contain more than one frame per clock + + always @(posedge rx_clk) begin + rx_ip_data_d <= rx_ip_data; + rx_ip_sof_d <= rx_ip_sof; + if (rx_ip_sof != 4'h0) begin + rx_ip_sof_hold <= rx_ip_sof; + end + rx_sof <= |rx_ip_sof_d; + if (rx_ip_sof_hold[0] == 1'b1) begin + rx_data <= rx_ip_data; + end else if (rx_ip_sof_hold[1] == 1'b1) begin + rx_data <= {rx_ip_data[ 7:0], rx_ip_data_d[31: 8]}; + end else if (rx_ip_sof_hold[2] == 1'b1) begin + rx_data <= {rx_ip_data[15:0], rx_ip_data_d[31:16]}; + end else if (rx_ip_sof_hold[3] == 1'b1) begin + rx_data <= {rx_ip_data[23:0], rx_ip_data_d[31:24]}; + end else begin + rx_data <= 32'd0; + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/axi_ctrlif.vhd b/src/adi/hdl/library/common/axi_ctrlif.vhd new file mode 100644 index 00000000..ddf25aeb --- /dev/null +++ b/src/adi/hdl/library/common/axi_ctrlif.vhd @@ -0,0 +1,148 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axi_ctrlif is + generic + ( + C_NUM_REG : integer := 32; + C_S_AXI_DATA_WIDTH : integer := 32; + C_S_AXI_ADDR_WIDTH : integer := 32; + C_FAMILY : string := "virtex6" + ); + port + ( + -- AXI bus interface + s_axi_aclk : in std_logic; + s_axi_aresetn : in std_logic; + s_axi_awaddr : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + s_axi_awvalid : in std_logic; + s_axi_wdata : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + s_axi_wstrb : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0); + s_axi_wvalid : in std_logic; + s_axi_bready : in std_logic; + s_axi_araddr : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + s_axi_arvalid : in std_logic; + s_axi_rready : in std_logic; + s_axi_arready : out std_logic; + s_axi_rdata : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + s_axi_rresp : out std_logic_vector(1 downto 0); + s_axi_rvalid : out std_logic; + s_axi_wready : out std_logic; + s_axi_bresp : out std_logic_vector(1 downto 0); + s_axi_bvalid : out std_logic; + s_axi_awready : out std_logic; + + rd_addr : out integer range 0 to C_NUM_REG - 1; + rd_data : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + rd_ack : out std_logic; + rd_stb : in std_logic; + + wr_addr : out integer range 0 to C_NUM_REG - 1; + wr_data : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + wr_ack : in std_logic; + wr_stb : out std_logic + ); +end entity axi_ctrlif; + + +architecture Behavioral of axi_ctrlif is + type state_type is (IDLE, RESP, ACK); + signal rd_state : state_type; + signal wr_state : state_type; +begin + process (s_axi_aclk) + begin + if rising_edge(s_axi_aclk) then + if s_axi_aresetn = '0' then + rd_state <= IDLE; + else + case rd_state is + when IDLE => + if s_axi_arvalid = '1' then + rd_state <= RESP; + rd_addr <= to_integer(unsigned(s_axi_araddr((C_S_AXI_ADDR_WIDTH-1) downto 2))); + end if; + when RESP => + if rd_stb = '1' and s_axi_rready = '1' then + rd_state <= IDLE; + end if; + when others => null; + end case; + end if; + end if; + end process; + + s_axi_arready <= '1' when rd_state = IDLE else '0'; + s_axi_rvalid <= '1' when rd_state = RESP and rd_stb = '1' else '0'; + s_axi_rresp <= "00"; + rd_ack <= '1' when rd_state = RESP and s_axi_rready = '1' else '0'; + s_axi_rdata <= rd_data; + + process (s_axi_aclk) + begin + if rising_edge(s_axi_aclk) then + if s_axi_aresetn = '0' then + wr_state <= IDLE; + else + case wr_state is + when IDLE => + if s_axi_awvalid = '1' and s_axi_wvalid = '1' and wr_ack = '1' then + wr_state <= ACK; + end if; + when ACK => + wr_state <= RESP; + when RESP => + if s_axi_bready = '1' then + wr_state <= IDLE; + end if; + end case; + end if; + end if; + end process; + + wr_stb <= '1' when s_axi_awvalid = '1' and s_axi_wvalid = '1' and wr_state = IDLE else '0'; + wr_data <= s_axi_wdata; + wr_addr <= to_integer(unsigned(s_axi_awaddr((C_S_AXI_ADDR_WIDTH-1) downto 2))); + + s_axi_awready <= '1' when wr_state = ACK else '0'; + s_axi_wready <= '1' when wr_state = ACK else '0'; + + s_axi_bresp <= "00"; + s_axi_bvalid <= '1' when wr_state = RESP else '0'; +end; diff --git a/src/adi/hdl/library/common/axi_streaming_dma_rx_fifo.vhd b/src/adi/hdl/library/common/axi_streaming_dma_rx_fifo.vhd new file mode 100644 index 00000000..b0e26a89 --- /dev/null +++ b/src/adi/hdl/library/common/axi_streaming_dma_rx_fifo.vhd @@ -0,0 +1,117 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.dma_fifo; + +entity axi_streaming_dma_rx_fifo is + generic ( + RAM_ADDR_WIDTH : integer := 3; + FIFO_DWIDTH : integer := 32 + ); + port ( + clk : in std_logic; + resetn : in std_logic; + fifo_reset : in std_logic; + + -- Enable DMA interface + enable : in Boolean; + + period_len : in integer range 0 to 65535; + + -- Read port + m_axis_aclk : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(FIFO_DWIDTH-1 downto 0); + m_axis_tlast : out std_logic; + m_axis_tvalid : out std_logic; + m_axis_tkeep : out std_logic_vector(3 downto 0); + + -- Write port + in_stb : in std_logic; + in_ack : out std_logic; + in_data : in std_logic_vector(FIFO_DWIDTH-1 downto 0) + ); +end; + +architecture imp of axi_streaming_dma_rx_fifo is + signal out_stb : std_logic; + + signal period_count : integer range 0 to 65535; + signal last : std_logic; +begin + + m_axis_tvalid <= out_stb; + + fifo: entity dma_fifo + generic map ( + RAM_ADDR_WIDTH => RAM_ADDR_WIDTH, + FIFO_DWIDTH => FIFO_DWIDTH + ) + port map ( + clk => clk, + resetn => resetn, + fifo_reset => fifo_reset, + in_stb => in_stb, + in_ack => in_ack, + in_data => in_data, + out_stb => out_stb, + out_ack => m_axis_tready, + out_data => m_axis_tdata + ); + + m_axis_tkeep <= "1111"; + m_axis_tlast <= '1' when period_count = 0 else '0'; + + period_counter: process(m_axis_aclk) is + begin + if rising_edge(m_axis_aclk) then + if resetn = '0' then + period_count <= period_len; + else + if out_stb = '1' and m_axis_tready = '1' then + if period_count = 0 then + period_count <= period_len; + else + period_count <= period_count - 1; + end if; + end if; + end if; + end if; + end process; +end; diff --git a/src/adi/hdl/library/common/axi_streaming_dma_tx_fifo.vhd b/src/adi/hdl/library/common/axi_streaming_dma_tx_fifo.vhd new file mode 100644 index 00000000..20671b02 --- /dev/null +++ b/src/adi/hdl/library/common/axi_streaming_dma_tx_fifo.vhd @@ -0,0 +1,111 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.dma_fifo; + +entity axi_streaming_dma_tx_fifo is + generic ( + RAM_ADDR_WIDTH : integer := 3; + FIFO_DWIDTH : integer := 32 + ); + port ( + clk : in std_logic; + resetn : in std_logic; + fifo_reset : in std_logic; + + -- Enable DMA interface + enable : in Boolean; + + -- Write port + s_axis_aclk : in std_logic; + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(FIFO_DWIDTH-1 downto 0); + s_axis_tlast : in std_logic; + s_axis_tvalid : in std_logic; + + -- Read port + out_stb : out std_logic; + out_ack : in std_logic; + out_data : out std_logic_vector(FIFO_DWIDTH-1 downto 0) + ); +end; + +architecture imp of axi_streaming_dma_tx_fifo is + signal in_ack : std_logic; + signal drain_dma : Boolean; +begin + + fifo: entity dma_fifo + generic map ( + RAM_ADDR_WIDTH => RAM_ADDR_WIDTH, + FIFO_DWIDTH => FIFO_DWIDTH + ) + port map ( + clk => clk, + resetn => resetn, + fifo_reset => fifo_reset, + in_stb => s_axis_tvalid, + in_ack => in_ack, + in_data => s_axis_tdata, + out_stb => out_stb, + out_ack => out_ack, + out_data => out_data + ); + + drain_process: process (s_axis_aclk) is + variable enable_d1 : Boolean; + begin + if rising_edge(s_axis_aclk) then + if resetn = '0' then + drain_dma <= False; + else + if s_axis_tlast = '1' then + drain_dma <= False; + elsif not enable_d1 and enable then + drain_dma <= False; + elsif enable_d1 and not enable then + drain_dma <= True; + end if; + enable_d1 := enable; + end if; + end if; + end process; + + s_axis_tready <= '1' when in_ack = '1' or drain_dma else '0'; +end; diff --git a/src/adi/hdl/library/common/dma_fifo.vhd b/src/adi/hdl/library/common/dma_fifo.vhd new file mode 100644 index 00000000..7143d9cc --- /dev/null +++ b/src/adi/hdl/library/common/dma_fifo.vhd @@ -0,0 +1,112 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity dma_fifo is + generic ( + RAM_ADDR_WIDTH : integer := 3; + FIFO_DWIDTH : integer := 32 + ); + port ( + clk : in std_logic; + resetn : in std_logic; + fifo_reset : in std_logic; + + -- Write port + in_stb : in std_logic; + in_ack : out std_logic; + in_data : in std_logic_vector(FIFO_DWIDTH-1 downto 0); + + -- Read port + out_stb : out std_logic; + out_ack : in std_logic; + out_data : out std_logic_vector(FIFO_DWIDTH-1 downto 0) + ); +end; + +architecture imp of dma_fifo is + + constant FIFO_MAX : natural := 2**RAM_ADDR_WIDTH -1; + type MEM is array (0 to FIFO_MAX) of std_logic_vector(FIFO_DWIDTH - 1 downto 0); + signal data_fifo : MEM; + signal wr_addr : natural range 0 to FIFO_MAX; + signal rd_addr : natural range 0 to FIFO_MAX; + signal not_full, not_empty : Boolean; + +begin + in_ack <= '1' when not_full else '0'; + + out_stb <= '1' when not_empty else '0'; + out_data <= data_fifo(rd_addr); + + fifo_data: process (clk) is + begin + if rising_edge(clk) then + if not_full then + data_fifo(wr_addr) <= in_data; + end if; + end if; + end process; + + fifo_ctrl: process (clk) is + variable free_cnt : integer range 0 to FIFO_MAX + 1; + begin + if rising_edge(clk) then + if (resetn = '0') or (fifo_reset = '1') then + wr_addr <= 0; + rd_addr <= 0; + free_cnt := FIFO_MAX + 1; + not_empty <= False; + not_full <= True; + else + if in_stb = '1' and not_full then + wr_addr <= (wr_addr + 1) mod (FIFO_MAX + 1); + free_cnt := free_cnt - 1; + end if; + + if out_ack = '1' and not_empty then + rd_addr <= (rd_addr + 1) mod (FIFO_MAX + 1); + free_cnt := free_cnt + 1; + end if; + + not_full <= not (free_cnt = 0); + not_empty <= not (free_cnt = FIFO_MAX + 1); + end if; + end if; + end process; +end; diff --git a/src/adi/hdl/library/common/pl330_dma_fifo.vhd b/src/adi/hdl/library/common/pl330_dma_fifo.vhd new file mode 100644 index 00000000..5a4f8ea9 --- /dev/null +++ b/src/adi/hdl/library/common/pl330_dma_fifo.vhd @@ -0,0 +1,175 @@ +-- *************************************************************************** +-- *************************************************************************** +-- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +-- +-- In this HDL repository, there are many different and unique modules, consisting +-- of various HDL (Verilog or VHDL) components. The individual modules are +-- developed independently, and may be accompanied by separate and unique license +-- terms. +-- +-- The user should read each of these license terms, and understand the +-- freedoms and responsibilities that he or she has by using this source/core. +-- +-- This core 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. +-- +-- Redistribution and use of source or resulting binaries, with or without modification +-- of this file, are permitted under one of the following two license terms: +-- +-- 1. The GNU General Public License version 2 as published by the +-- Free Software Foundation, which can be found in the top level directory +-- of this repository (LICENSE_GPL2), and also online at: +-- +-- +-- OR +-- +-- 2. An ADI specific BSD license, which can be found in the top level directory +-- of this repository (LICENSE_ADIBSD), and also on-line at: +-- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +-- This will allow to generate bit files and not release the source code, +-- as long as it attaches to an ADI device. +-- +-- *************************************************************************** +-- *************************************************************************** + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.dma_fifo; + +entity pl330_dma_fifo is + generic ( + RAM_ADDR_WIDTH : integer := 3; + FIFO_DWIDTH : integer := 32; + FIFO_DIRECTION : integer := 0 -- 0 = write FIFO, 1 = read FIFO + ); + port ( + clk : in std_logic; + resetn : in std_logic; + fifo_reset : in std_logic; + + -- Enable DMA interface + enable : in Boolean; + + -- Write port + in_stb : in std_logic; + in_ack : out std_logic; + in_data : in std_logic_vector(FIFO_DWIDTH-1 downto 0); + + -- Read port + out_stb : out std_logic; + out_ack : in std_logic; + out_data : out std_logic_vector(FIFO_DWIDTH-1 downto 0); + + -- PL330 DMA interface + dclk : in std_logic; + dresetn : in std_logic; + davalid : in std_logic; + daready : out std_logic; + datype : in std_logic_vector(1 downto 0); + drvalid : out std_logic; + drready : in std_logic; + drtype : out std_logic_vector(1 downto 0); + drlast : out std_logic; + + DBG : out std_logic_vector(7 downto 0) + ); +end; + +architecture imp of pl330_dma_fifo is + signal request_data : Boolean; + + type state_type is (IDLE, REQUEST, WAITING, FLUSH); + signal state : state_type; + signal i_in_ack : std_logic; + signal i_out_stb : std_logic; +begin + + in_ack <= i_in_ack; + out_stb <= i_out_stb; + + fifo: entity dma_fifo + generic map ( + RAM_ADDR_WIDTH => RAM_ADDR_WIDTH, + FIFO_DWIDTH => FIFO_DWIDTH + ) + port map ( + clk => clk, + resetn => resetn, + fifo_reset => fifo_reset, + in_stb => in_stb, + in_ack => i_in_ack, + in_data => in_data, + out_stb => i_out_stb, + out_ack => out_ack, + out_data => out_data + ); + + request_data <= i_in_ack = '1' when FIFO_DIRECTION = 0 else i_out_stb = '1'; + + drlast <= '0'; + daready <= '1'; + + drvalid <= '1' when (state = REQUEST) or (state = FLUSH) else '0'; + drtype <= "00" when state = REQUEST else "10"; + + DBG(0) <= davalid; + DBG(2 downto 1) <= datype; + DBG(3) <= '1' when request_data else '0'; + + process (state) + begin + case state is + when IDLE => DBG(5 downto 4) <= "00"; + when REQUEST => DBG(5 downto 4) <= "01"; + when WAITING => DBG(5 downto 4) <= "10"; + when FLUSH => DBG(5 downto 4) <= "11"; + end case; + end process; + + pl330_req_fsm: process (dclk) is + begin + if rising_edge(dclk) then + if dresetn = '0' then + state <= IDLE; + else + -- The controller may send a FLUSH request at any time and it won't + -- respond to any of our requests until we've ack the FLUSH request. + -- The FLUSH request is also supposed to reset our state machine, so + -- go back to idle after having acked the FLUSH. + if davalid = '1' and datype = "10" then + state <= FLUSH; + else + case state is + -- Nothing to do, wait for the fifo to run empty + when IDLE => + if request_data and enable then + state <= REQUEST; + end if; + -- Send out a request to the PL330 + when REQUEST => + if drready = '1' then + state <= WAITING; + end if; + -- Wait for a ACK from the PL330 that it did transfer the data + when WAITING => + if fifo_reset = '1' then + state <= IDLE; + elsif davalid = '1' then + if datype = "00" then + state <= IDLE; + end if; + end if; + -- Send out an ACK for the flush + when FLUSH => + if drready = '1' then + state <= IDLE; + end if; + end case; + end if; + end if; + end if; + end process; +end; diff --git a/src/adi/hdl/library/common/up_adc_channel.v b/src/adi/hdl/library/common/up_adc_channel.v new file mode 100644 index 00000000..f81d9bf1 --- /dev/null +++ b/src/adi/hdl/library/common/up_adc_channel.v @@ -0,0 +1,491 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_adc_channel #( + + // parameters + + parameter COMMON_ID = 6'h01, + parameter CHANNEL_ID = 4'h0, + parameter USERPORTS_DISABLE = 0, + parameter DATAFORMAT_DISABLE = 0, + parameter DCFILTER_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 0) ( + + // adc interface + + input adc_clk, + input adc_rst, + output adc_enable, + output adc_iqcor_enb, + output adc_dcfilt_enb, + output adc_dfmt_se, + output adc_dfmt_type, + output adc_dfmt_enable, + output [15:0] adc_dcfilt_offset, + output [15:0] adc_dcfilt_coeff, + output [15:0] adc_iqcor_coeff_1, + output [15:0] adc_iqcor_coeff_2, + output [ 3:0] adc_pnseq_sel, + output [ 3:0] adc_data_sel, + input adc_pn_err, + input adc_pn_oos, + input adc_or, + output up_adc_pn_err, + output up_adc_pn_oos, + output up_adc_or, + + // user controls + + output up_usr_datatype_be, + output up_usr_datatype_signed, + output [ 7:0] up_usr_datatype_shift, + output [ 7:0] up_usr_datatype_total_bits, + output [ 7:0] up_usr_datatype_bits, + output [15:0] up_usr_decimation_m, + output [15:0] up_usr_decimation_n, + input adc_usr_datatype_be, + input adc_usr_datatype_signed, + input [ 7:0] adc_usr_datatype_shift, + input [ 7:0] adc_usr_datatype_total_bits, + input [ 7:0] adc_usr_datatype_bits, + input [15:0] adc_usr_decimation_m, + input [15:0] adc_usr_decimation_n, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack); + + // internal registers + + reg up_wack_int = 'd0; + reg up_adc_lb_enb = 'd0; + reg up_adc_pn_sel = 'd0; + reg up_adc_iqcor_enb = 'd0; + reg up_adc_dcfilt_enb = 'd0; + reg up_adc_dfmt_se = 'd0; + reg up_adc_dfmt_type = 'd0; + reg up_adc_dfmt_enable = 'd0; + reg up_adc_pn_type = 'd0; + reg up_adc_enable = 'd0; + reg up_adc_pn_err_int = 'd0; + reg up_adc_pn_oos_int = 'd0; + reg up_adc_or_int = 'd0; + reg [15:0] up_adc_dcfilt_offset = 'd0; + reg [15:0] up_adc_dcfilt_coeff = 'd0; + reg [15:0] up_adc_iqcor_coeff_1 = 'd0; + reg [15:0] up_adc_iqcor_coeff_2 = 'd0; + reg [ 3:0] up_adc_pnseq_sel = 'd0; + reg [ 3:0] up_adc_data_sel = 'd0; + reg up_usr_datatype_be_int = 'd0; + reg up_usr_datatype_signed_int = 'd0; + reg [ 7:0] up_usr_datatype_shift_int = 'd0; + reg [ 7:0] up_usr_datatype_total_bits_int = 'd0; + reg [ 7:0] up_usr_datatype_bits_int = 'd0; + reg [15:0] up_usr_decimation_m_int = 'd0; + reg [15:0] up_usr_decimation_n_int = 'd0; + reg up_rack_int = 'd0; + reg [31:0] up_rdata_int = 'd0; + reg [15:0] up_adc_iqcor_coeff_tc_1 = 'd0; + reg [15:0] up_adc_iqcor_coeff_tc_2 = 'd0; + reg [ 3:0] up_adc_pnseq_sel_m = 'd0; + reg [ 3:0] up_adc_data_sel_m = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire up_adc_pn_err_s; + wire up_adc_pn_oos_s; + wire up_adc_or_s; + + // 2's complement function + + function [15:0] sm2tc; + input [15:0] din; + reg [15:0] dp; + reg [15:0] dn; + reg [15:0] dout; + begin + dp = {1'b0, din[14:0]}; + dn = ~dp + 1'b1; + dout = (din[15] == 1'b1) ? dn : dp; + sm2tc = dout; + end + endfunction + + // up control/status + + assign up_adc_pn_err = up_adc_pn_err_int; + assign up_adc_pn_oos = up_adc_pn_oos_int; + assign up_adc_or = up_adc_or_int; + assign up_usr_datatype_be = up_usr_datatype_be_int; + assign up_usr_datatype_signed = up_usr_datatype_signed_int; + assign up_usr_datatype_shift = up_usr_datatype_shift_int; + assign up_usr_datatype_total_bits = up_usr_datatype_total_bits_int; + assign up_usr_datatype_bits = up_usr_datatype_bits_int; + assign up_usr_decimation_m = up_usr_decimation_m_int; + assign up_usr_decimation_n = up_usr_decimation_n_int; + + // decode block select + + assign up_wreq_s = ((up_waddr[13:8] == COMMON_ID) && (up_waddr[7:4] == CHANNEL_ID)) ? up_wreq : 1'b0; + assign up_rreq_s = ((up_raddr[13:8] == COMMON_ID) && (up_raddr[7:4] == CHANNEL_ID)) ? up_rreq : 1'b0; + + // processor write interface + + assign up_wack = up_wack_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_wack_int <= 'd0; + up_adc_lb_enb <= 'd0; + up_adc_pn_sel <= 'd0; + end else begin + up_wack_int <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_adc_lb_enb <= up_wdata[11]; + up_adc_pn_sel <= up_wdata[10]; + end + end + end + + generate + if (IQCORRECTION_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_iqcor_enb <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_iqcor_enb <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_adc_iqcor_enb <= up_wdata[9]; + end + end + end + end + endgenerate + + generate + if (DCFILTER_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_dcfilt_enb <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_dcfilt_enb <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_adc_dcfilt_enb <= up_wdata[8]; + end + end + end + end + endgenerate + + generate + if (DATAFORMAT_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_dfmt_se <= 'd0; + up_adc_dfmt_type <= 'd0; + up_adc_dfmt_enable <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_dfmt_se <= 'd0; + up_adc_dfmt_type <= 'd0; + up_adc_dfmt_enable <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_adc_dfmt_se <= up_wdata[6]; + up_adc_dfmt_type <= up_wdata[5]; + up_adc_dfmt_enable <= up_wdata[4]; + end + end + end + end + endgenerate + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_pn_type <= 'd0; + up_adc_enable <= 'd0; + up_adc_pn_err_int <= 'd0; + up_adc_pn_oos_int <= 'd0; + up_adc_or_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_adc_pn_type <= up_wdata[1]; + up_adc_enable <= up_wdata[0]; + end + if (up_adc_pn_err_s == 1'b1) begin + up_adc_pn_err_int <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h1)) begin + up_adc_pn_err_int <= up_adc_pn_err_int & ~up_wdata[2]; + end + if (up_adc_pn_oos_s == 1'b1) begin + up_adc_pn_oos_int <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h1)) begin + up_adc_pn_oos_int <= up_adc_pn_oos_int & ~up_wdata[1]; + end + if (up_adc_or_s == 1'b1) begin + up_adc_or_int <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h1)) begin + up_adc_or_int <= up_adc_or_int & ~up_wdata[0]; + end + end + end + + generate + if (DCFILTER_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_dcfilt_offset <= 'd0; + up_adc_dcfilt_coeff <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_dcfilt_offset <= 'd0; + up_adc_dcfilt_coeff <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h4)) begin + up_adc_dcfilt_offset <= up_wdata[31:16]; + up_adc_dcfilt_coeff <= up_wdata[15:0]; + end + end + end + end + endgenerate + + generate + if (IQCORRECTION_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_iqcor_coeff_1 <= 'd0; + up_adc_iqcor_coeff_2 <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_iqcor_coeff_1 <= 'd0; + up_adc_iqcor_coeff_2 <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h5)) begin + up_adc_iqcor_coeff_1 <= up_wdata[31:16]; + up_adc_iqcor_coeff_2 <= up_wdata[15:0]; + end + end + end + end + endgenerate + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_pnseq_sel <= 'd0; + up_adc_data_sel <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h6)) begin + up_adc_pnseq_sel <= up_wdata[19:16]; + up_adc_data_sel <= up_wdata[3:0]; + end + end + end + + generate + if (USERPORTS_DISABLE == 1) begin + always @(posedge up_clk) begin + up_usr_datatype_be_int <= 'd0; + up_usr_datatype_signed_int <= 'd0; + up_usr_datatype_shift_int <= 'd0; + up_usr_datatype_total_bits_int <= 'd0; + up_usr_datatype_bits_int <= 'd0; + up_usr_decimation_m_int <= 'd0; + up_usr_decimation_n_int <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_usr_datatype_be_int <= 'd0; + up_usr_datatype_signed_int <= 'd0; + up_usr_datatype_shift_int <= 'd0; + up_usr_datatype_total_bits_int <= 'd0; + up_usr_datatype_bits_int <= 'd0; + up_usr_decimation_m_int <= 'd0; + up_usr_decimation_n_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h8)) begin + up_usr_datatype_be_int <= up_wdata[25]; + up_usr_datatype_signed_int <= up_wdata[24]; + up_usr_datatype_shift_int <= up_wdata[23:16]; + up_usr_datatype_total_bits_int <= up_wdata[15:8]; + up_usr_datatype_bits_int <= up_wdata[7:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h9)) begin + up_usr_decimation_m_int <= up_wdata[31:16]; + up_usr_decimation_n_int <= up_wdata[15:0]; + end + end + end + end + endgenerate + + // processor read interface + + assign up_rack = up_rack_int; + assign up_rdata = up_rdata_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + end else begin + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[3:0]) + 4'h0: up_rdata_int <= { 20'd0, up_adc_lb_enb, up_adc_pn_sel, + up_adc_iqcor_enb, up_adc_dcfilt_enb, + 1'd0, up_adc_dfmt_se, up_adc_dfmt_type, up_adc_dfmt_enable, + 2'd0, up_adc_pn_type, up_adc_enable}; + 4'h1: up_rdata_int <= { 29'd0, up_adc_pn_err_int, up_adc_pn_oos_int, up_adc_or_int}; + 4'h4: up_rdata_int <= { up_adc_dcfilt_offset, up_adc_dcfilt_coeff}; + 4'h5: up_rdata_int <= { up_adc_iqcor_coeff_1, up_adc_iqcor_coeff_2}; + 4'h6: up_rdata_int <= { 12'd0, up_adc_pnseq_sel, 12'd0, up_adc_data_sel}; + 4'h8: up_rdata_int <= { 6'd0, adc_usr_datatype_be, adc_usr_datatype_signed, + adc_usr_datatype_shift, adc_usr_datatype_total_bits, + adc_usr_datatype_bits}; + 4'h9: up_rdata_int <= { adc_usr_decimation_m, adc_usr_decimation_n}; + default: up_rdata_int <= 0; + endcase + end else begin + up_rdata_int <= 32'd0; + end + end + end + + // change coefficients to 2's complements + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_iqcor_coeff_tc_1 <= 16'd0; + up_adc_iqcor_coeff_tc_2 <= 16'd0; + end else begin + up_adc_iqcor_coeff_tc_1 <= sm2tc(up_adc_iqcor_coeff_1); + up_adc_iqcor_coeff_tc_2 <= sm2tc(up_adc_iqcor_coeff_2); + end + end + + // data/pn sources + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_pnseq_sel_m <= 4'd0; + up_adc_data_sel_m <= 4'd0; + end else begin + case ({up_adc_pn_type, up_adc_pn_sel}) + 2'b10: up_adc_pnseq_sel_m <= 4'h1; + 2'b01: up_adc_pnseq_sel_m <= 4'h9; + default: up_adc_pnseq_sel_m <= up_adc_pnseq_sel; + endcase + if (up_adc_lb_enb == 1'b1) begin + up_adc_data_sel_m <= 4'h1; + end else begin + up_adc_data_sel_m <= up_adc_data_sel; + end + end + end + + // adc control & status + + up_xfer_cntrl #(.DATA_WIDTH(78)) i_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_adc_iqcor_enb, + up_adc_dcfilt_enb, + up_adc_dfmt_se, + up_adc_dfmt_type, + up_adc_dfmt_enable, + up_adc_enable, + up_adc_dcfilt_offset, + up_adc_dcfilt_coeff, + up_adc_iqcor_coeff_tc_1, + up_adc_iqcor_coeff_tc_2, + up_adc_pnseq_sel_m, + up_adc_data_sel_m}), + .up_xfer_done (), + .d_rst (adc_rst), + .d_clk (adc_clk), + .d_data_cntrl ({ adc_iqcor_enb, + adc_dcfilt_enb, + adc_dfmt_se, + adc_dfmt_type, + adc_dfmt_enable, + adc_enable, + adc_dcfilt_offset, + adc_dcfilt_coeff, + adc_iqcor_coeff_1, + adc_iqcor_coeff_2, + adc_pnseq_sel, + adc_data_sel})); + + up_xfer_status #(.DATA_WIDTH(3)) i_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({up_adc_pn_err_s, + up_adc_pn_oos_s, + up_adc_or_s}), + .d_rst (adc_rst), + .d_clk (adc_clk), + .d_data_status ({ adc_pn_err, + adc_pn_oos, + adc_or})); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_adc_common.v b/src/adi/hdl/library/common/up_adc_common.v new file mode 100644 index 00000000..2d55448e --- /dev/null +++ b/src/adi/hdl/library/common/up_adc_common.v @@ -0,0 +1,454 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_adc_common #( + + // parameters + + parameter ID = 0, + parameter CONFIG = 0, + parameter COMMON_ID = 6'h00, + parameter DRP_DISABLE = 0, + parameter USERPORTS_DISABLE = 0, + parameter GPIO_DISABLE = 0, + parameter START_CODE_DISABLE = 0) ( + + // clock reset + + output mmcm_rst, + + // adc interface + + input adc_clk, + output adc_rst, + output adc_r1_mode, + output adc_ddr_edgesel, + output adc_pin_mode, + input adc_status, + input adc_sync_status, + input adc_status_ovf, + input [31:0] adc_clk_ratio, + output [31:0] adc_start_code, + output adc_sref_sync, + output adc_sync, + input [31:0] up_pps_rcounter, + input up_pps_status, + output reg up_pps_irq_mask, + + // channel interface + + output up_adc_ce, + input up_status_pn_err, + input up_status_pn_oos, + input up_status_or, + + // drp interface + + output up_drp_sel, + output up_drp_wr, + output [11:0] up_drp_addr, + output [31:0] up_drp_wdata, + input [31:0] up_drp_rdata, + input up_drp_ready, + input up_drp_locked, + + // user channel control + + output [ 7:0] up_usr_chanmax_out, + input [ 7:0] up_usr_chanmax_in, + input [31:0] up_adc_gpio_in, + output [31:0] up_adc_gpio_out, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack); + + // parameters + + localparam VERSION = 32'h000a0062; + + // internal registers + + reg up_adc_clk_enb_int = 'd1; + reg up_core_preset = 'd1; + reg up_mmcm_preset = 'd1; + reg up_wack_int = 'd0; + reg [31:0] up_scratch = 'd0; + reg up_adc_clk_enb = 'd0; + reg up_mmcm_resetn = 'd0; + reg up_resetn = 'd0; + reg up_adc_sync = 'd0; + reg up_adc_sref_sync = 'd0; + reg up_adc_r1_mode = 'd0; + reg up_adc_ddr_edgesel = 'd0; + reg up_adc_pin_mode = 'd0; + reg up_status_ovf = 'd0; + reg [ 7:0] up_usr_chanmax_int = 'd0; + reg [31:0] up_adc_start_code = 'd0; + reg [31:0] up_adc_gpio_out_int = 'd0; + reg [31:0] up_timer = 'd0; + reg up_rack_int = 'd0; + reg [31:0] up_rdata_int = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire up_status_s; + wire up_sync_status_s; + wire up_status_ovf_s; + wire up_cntrl_xfer_done_s; + wire [31:0] up_adc_clk_count_s; + wire up_drp_status_s; + wire up_drp_rwn_s; + wire [31:0] up_drp_rdata_hold_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == COMMON_ID) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == COMMON_ID) ? up_rreq : 1'b0; + + // processor write interface + + assign up_wack = up_wack_int; + assign up_adc_ce = up_adc_clk_enb_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_clk_enb_int <= 1'd1; + up_core_preset <= 1'd1; + up_mmcm_preset <= 1'd1; + up_wack_int <= 'd0; + up_scratch <= 'd0; + up_adc_clk_enb <= 'd0; + up_mmcm_resetn <= 'd0; + up_resetn <= 'd0; + up_adc_sync <= 'd0; + up_adc_sref_sync <= 'd0; + up_adc_r1_mode <= 'd0; + up_adc_ddr_edgesel <= 'd0; + up_adc_pin_mode <= 'd0; + up_pps_irq_mask <= 1'b1; + end else begin + up_adc_clk_enb_int <= ~up_adc_clk_enb; + up_core_preset <= ~up_resetn; + up_mmcm_preset <= ~up_mmcm_resetn; + up_wack_int <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h02)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h04)) begin + up_pps_irq_mask <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h10)) begin + up_adc_clk_enb <= up_wdata[2]; + up_mmcm_resetn <= up_wdata[1]; + up_resetn <= up_wdata[0]; + end + if (up_adc_sync == 1'b1) begin + if (up_cntrl_xfer_done_s == 1'b1) begin + up_adc_sync <= 1'b0; + end + end else if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h11)) begin + up_adc_sync <= up_wdata[3]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h11)) begin + up_adc_sref_sync <= up_wdata[4]; + up_adc_r1_mode <= up_wdata[2]; + up_adc_ddr_edgesel <= up_wdata[1]; + up_adc_pin_mode <= up_wdata[0]; + end + end + end + + generate + if (DRP_DISABLE == 1) begin + + assign up_drp_sel = 'd0; + assign up_drp_wr = 'd0; + assign up_drp_status_s = 'd0; + assign up_drp_rwn_s = 'd0; + assign up_drp_addr = 'd0; + assign up_drp_wdata = 'd0; + assign up_drp_rdata_hold_s = 'd0; + + end else begin + + reg up_drp_sel_int = 'd0; + reg up_drp_wr_int = 'd0; + reg up_drp_status_int = 'd0; + reg up_drp_rwn_int = 'd0; + reg [11:0] up_drp_addr_int = 'd0; + reg [31:0] up_drp_wdata_int = 'd0; + reg [31:0] up_drp_rdata_hold_int = 'd0; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_drp_sel_int <= 'd0; + up_drp_wr_int <= 'd0; + up_drp_status_int <= 'd0; + up_drp_rwn_int <= 'd0; + up_drp_addr_int <= 'd0; + up_drp_wdata_int <= 'd0; + up_drp_rdata_hold_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_sel_int <= 1'b1; + up_drp_wr_int <= ~up_wdata[28]; + end else begin + up_drp_sel_int <= 1'b0; + up_drp_wr_int <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_status_int <= 1'b1; + end else if (up_drp_ready == 1'b1) begin + up_drp_status_int <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_rwn_int <= up_wdata[28]; + up_drp_addr_int <= up_wdata[27:16]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1e)) begin + up_drp_wdata_int <= up_wdata; + end + if (up_drp_ready == 1'b1) begin + up_drp_rdata_hold_int <= up_drp_rdata; + end + end + end + + assign up_drp_sel = up_drp_sel_int; + assign up_drp_wr = up_drp_wr_int; + assign up_drp_status_s = up_drp_status_int; + assign up_drp_rwn_s = up_drp_rwn_int; + assign up_drp_addr = up_drp_addr_int; + assign up_drp_wdata = up_drp_wdata_int; + assign up_drp_rdata_hold_s = up_drp_rdata_hold_int; + + end + endgenerate + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_status_ovf <= 'd0; + end else begin + if (up_status_ovf_s == 1'b1) begin + up_status_ovf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h22)) begin + up_status_ovf <= up_status_ovf & ~up_wdata[2]; + end + end + end + + assign up_usr_chanmax_out = up_usr_chanmax_int; + + generate + if (USERPORTS_DISABLE == 1) begin + always @(posedge up_clk) begin + up_usr_chanmax_int <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_usr_chanmax_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h28)) begin + up_usr_chanmax_int <= up_wdata[7:0]; + end + end + end + end + endgenerate + + assign up_adc_gpio_out = up_adc_gpio_out_int; + + generate + if (GPIO_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_gpio_out_int <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_gpio_out_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h2f)) begin + up_adc_gpio_out_int <= up_wdata; + end + end + end + end + endgenerate + + generate + if (START_CODE_DISABLE == 1) begin + always @(posedge up_clk) begin + up_adc_start_code <= 'd0; + end + end else begin + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_adc_start_code <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h29)) begin + up_adc_start_code <= up_wdata[31:0]; + end + end + end + end + endgenerate + + // timer with premature termination + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_timer <= 32'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h40)) begin + up_timer <= up_wdata; + end else if (up_timer > 0) begin + up_timer <= up_timer - 1'b1; + end + end + end + + // processor read interface + + assign up_rack = up_rack_int; + assign up_rdata = up_rdata_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + end else begin + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[7:0]) + 8'h00: up_rdata_int <= VERSION; + 8'h01: up_rdata_int <= ID; + 8'h02: up_rdata_int <= up_scratch; + 8'h03: up_rdata_int <= CONFIG; + 8'h04: up_rdata_int <= {31'b0, up_pps_irq_mask}; + 8'h10: up_rdata_int <= {29'd0, up_adc_clk_enb, up_mmcm_resetn, up_resetn}; + 8'h11: up_rdata_int <= {27'd0, up_adc_sref_sync, up_adc_sync, up_adc_r1_mode, + up_adc_ddr_edgesel, up_adc_pin_mode}; + 8'h15: up_rdata_int <= up_adc_clk_count_s; + 8'h16: up_rdata_int <= adc_clk_ratio; + 8'h17: up_rdata_int <= {28'd0, up_status_pn_err, up_status_pn_oos, up_status_or, up_status_s}; + 8'h1a: up_rdata_int <= {31'd0, up_sync_status_s}; + 8'h1c: up_rdata_int <= {3'd0, up_drp_rwn_s, up_drp_addr, 16'b0}; + 8'h1d: up_rdata_int <= {14'd0, up_drp_locked, up_drp_status_s, 16'b0}; + 8'h1e: up_rdata_int <= up_drp_wdata; + 8'h1f: up_rdata_int <= up_drp_rdata_hold_s; + 8'h22: up_rdata_int <= {29'd0, up_status_ovf, 2'b0}; + 8'h23: up_rdata_int <= 32'd8; + 8'h28: up_rdata_int <= {24'd0, up_usr_chanmax_in}; + 8'h29: up_rdata_int <= up_adc_start_code; + 8'h2e: up_rdata_int <= up_adc_gpio_in; + 8'h2f: up_rdata_int <= up_adc_gpio_out_int; + 8'h30: up_rdata_int <= up_pps_rcounter; + 8'h31: up_rdata_int <= {31'b0, up_pps_status}; + 8'h40: up_rdata_int <= up_timer; + default: up_rdata_int <= 0; + endcase + end else begin + up_rdata_int <= 32'd0; + end + end + end + + // resets + + ad_rst i_mmcm_rst_reg (.rst_async(up_mmcm_preset), .clk(up_clk), .rstn(), .rst(mmcm_rst)); + ad_rst i_core_rst_reg (.rst_async(up_core_preset), .clk(adc_clk), .rstn(), .rst(adc_rst)); + + // adc control & status + + up_xfer_cntrl #(.DATA_WIDTH(37)) i_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_adc_sref_sync, + up_adc_sync, + up_adc_start_code, + up_adc_r1_mode, + up_adc_ddr_edgesel, + up_adc_pin_mode}), + .up_xfer_done (up_cntrl_xfer_done_s), + .d_rst (adc_rst), + .d_clk (adc_clk), + .d_data_cntrl ({ adc_sref_sync, + adc_sync, + adc_start_code, + adc_r1_mode, + adc_ddr_edgesel, + adc_pin_mode})); + + up_xfer_status #(.DATA_WIDTH(3)) i_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({up_sync_status_s, + up_status_s, + up_status_ovf_s}), + .d_rst (adc_rst), + .d_clk (adc_clk), + .d_data_status ({ adc_sync_status, + adc_status, + adc_status_ovf})); + + // adc clock monitor + + up_clock_mon i_clock_mon ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_d_count (up_adc_clk_count_s), + .d_rst (adc_rst), + .d_clk (adc_clk)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_axi.v b/src/adi/hdl/library/common/up_axi.v new file mode 100644 index 00000000..8811a270 --- /dev/null +++ b/src/adi/hdl/library/common/up_axi.v @@ -0,0 +1,243 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_axi #( + + parameter ADDRESS_WIDTH = 14, + parameter AXI_ADDRESS_WIDTH = 16) ( + + // reset and clocks + + input up_rstn, + input up_clk, + + // axi4 interface + + input up_axi_awvalid, + input [(AXI_ADDRESS_WIDTH-1):0] up_axi_awaddr, + output up_axi_awready, + input up_axi_wvalid, + input [31:0] up_axi_wdata, + input [ 3:0] up_axi_wstrb, + output up_axi_wready, + output up_axi_bvalid, + output [ 1:0] up_axi_bresp, + input up_axi_bready, + input up_axi_arvalid, + input [(AXI_ADDRESS_WIDTH-1):0] up_axi_araddr, + output up_axi_arready, + output up_axi_rvalid, + output [ 1:0] up_axi_rresp, + output [31:0] up_axi_rdata, + input up_axi_rready, + + // pcore interface + + output up_wreq, + output [(ADDRESS_WIDTH-1):0] up_waddr, + output [31:0] up_wdata, + input up_wack, + output up_rreq, + output [(ADDRESS_WIDTH-1):0] up_raddr, + input [31:0] up_rdata, + input up_rack); + + // internal registers + + reg up_axi_awready_int = 'd0; + reg up_axi_wready_int = 'd0; + reg up_axi_bvalid_int = 'd0; + reg up_wack_d = 'd0; + reg up_wsel = 'd0; + reg up_wreq_int = 'd0; + reg [(ADDRESS_WIDTH-1):0] up_waddr_int = 'd0; + reg [31:0] up_wdata_int = 'd0; + reg [ 4:0] up_wcount = 'd0; + reg up_axi_arready_int = 'd0; + reg up_axi_rvalid_int = 'd0; + reg [31:0] up_axi_rdata_int = 'd0; + reg up_rack_d = 'd0; + reg [31:0] up_rdata_d = 'd0; + reg up_rsel = 'd0; + reg up_rreq_int = 'd0; + reg [(ADDRESS_WIDTH-1):0] up_raddr_int = 'd0; + reg [ 4:0] up_rcount = 'd0; + + // internal signals + + wire up_wack_s; + wire up_rack_s; + wire [31:0] up_rdata_s; + + // write channel interface + + assign up_axi_awready = up_axi_awready_int; + assign up_axi_wready = up_axi_wready_int; + assign up_axi_bvalid = up_axi_bvalid_int; + assign up_axi_bresp = 2'd0; + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_axi_awready_int <= 'd0; + up_axi_wready_int <= 'd0; + up_axi_bvalid_int <= 'd0; + end else begin + if (up_axi_awready_int == 1'b1) begin + up_axi_awready_int <= 1'b0; + end else if (up_wack_s == 1'b1) begin + up_axi_awready_int <= 1'b1; + end + if (up_axi_wready_int == 1'b1) begin + up_axi_wready_int <= 1'b0; + end else if (up_wack_s == 1'b1) begin + up_axi_wready_int <= 1'b1; + end + if ((up_axi_bready == 1'b1) && (up_axi_bvalid_int == 1'b1)) begin + up_axi_bvalid_int <= 1'b0; + end else if (up_wack_d == 1'b1) begin + up_axi_bvalid_int <= 1'b1; + end + end + end + + assign up_wreq = up_wreq_int; + assign up_waddr = up_waddr_int; + assign up_wdata = up_wdata_int; + assign up_wack_s = (up_wcount == 5'h1f) ? 1'b1 : (up_wcount[4] & up_wack); + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_wack_d <= 'd0; + up_wsel <= 'd0; + up_wreq_int <= 'd0; + up_waddr_int <= 'd0; + up_wdata_int <= 'd0; + up_wcount <= 'd0; + end else begin + up_wack_d <= up_wack_s; + if (up_wsel == 1'b1) begin + if ((up_axi_bready == 1'b1) && (up_axi_bvalid_int == 1'b1)) begin + up_wsel <= 1'b0; + end + up_wreq_int <= 1'b0; + up_waddr_int <= up_waddr_int; + up_wdata_int <= up_wdata_int; + end else begin + up_wsel <= up_axi_awvalid & up_axi_wvalid; + up_wreq_int <= up_axi_awvalid & up_axi_wvalid; + up_waddr_int <= up_axi_awaddr[(ADDRESS_WIDTH+1):2]; + up_wdata_int <= up_axi_wdata; + end + if (up_wack_s == 1'b1) begin + up_wcount <= 5'h00; + end else if (up_wcount[4] == 1'b1) begin + up_wcount <= up_wcount + 1'b1; + end else if (up_wreq_int == 1'b1) begin + up_wcount <= 5'h10; + end + end + end + + // read channel interface + + assign up_axi_arready = up_axi_arready_int; + assign up_axi_rvalid = up_axi_rvalid_int; + assign up_axi_rdata = up_axi_rdata_int; + assign up_axi_rresp = 2'd0; + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_axi_arready_int <= 'd0; + up_axi_rvalid_int <= 'd0; + up_axi_rdata_int <= 'd0; + end else begin + if (up_axi_arready_int == 1'b1) begin + up_axi_arready_int <= 1'b0; + end else if (up_rack_s == 1'b1) begin + up_axi_arready_int <= 1'b1; + end + if ((up_axi_rready == 1'b1) && (up_axi_rvalid_int == 1'b1)) begin + up_axi_rvalid_int <= 1'b0; + up_axi_rdata_int <= 32'd0; + end else if (up_rack_d == 1'b1) begin + up_axi_rvalid_int <= 1'b1; + up_axi_rdata_int <= up_rdata_d; + end + end + end + + assign up_rreq = up_rreq_int; + assign up_raddr = up_raddr_int; + assign up_rack_s = (up_rcount == 5'h1f) ? 1'b1 : (up_rcount[4] & up_rack); + assign up_rdata_s = (up_rcount == 5'h1f) ? {2{16'hdead}} : up_rdata; + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_rack_d <= 'd0; + up_rdata_d <= 'd0; + up_rsel <= 'd0; + up_rreq_int <= 'd0; + up_raddr_int <= 'd0; + up_rcount <= 'd0; + end else begin + up_rack_d <= up_rack_s; + up_rdata_d <= up_rdata_s; + if (up_rsel == 1'b1) begin + if ((up_axi_rready == 1'b1) && (up_axi_rvalid_int == 1'b1)) begin + up_rsel <= 1'b0; + end + up_rreq_int <= 1'b0; + up_raddr_int <= up_raddr_int; + end else begin + up_rsel <= up_axi_arvalid; + up_rreq_int <= up_axi_arvalid; + up_raddr_int <= up_axi_araddr[(ADDRESS_WIDTH+1):2]; + end + if (up_rack_s == 1'b1) begin + up_rcount <= 5'h00; + end else if (up_rcount[4] == 1'b1) begin + up_rcount <= up_rcount + 1'b1; + end else if (up_rreq_int == 1'b1) begin + up_rcount <= 5'h10; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_clkgen.v b/src/adi/hdl/library/common/up_clkgen.v new file mode 100644 index 00000000..0837c526 --- /dev/null +++ b/src/adi/hdl/library/common/up_clkgen.v @@ -0,0 +1,184 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_clkgen #( + + parameter ID = 0) ( + + // mmcm reset + + output mmcm_rst, + + // clock selection + + output clk_sel, + + // drp interface + + output reg up_drp_sel, + output reg up_drp_wr, + output reg [11:0] up_drp_addr, + output reg [15:0] up_drp_wdata, + input [15:0] up_drp_rdata, + input up_drp_ready, + input up_drp_locked, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack); + + localparam PCORE_VERSION = 32'h00040063; + + // internal registers + + reg up_mmcm_preset = 'd0; + reg [31:0] up_scratch = 'd0; + reg up_mmcm_resetn = 'd0; + reg up_resetn = 'd0; + reg up_drp_status = 'd0; + reg up_drp_rwn = 'd0; + reg [15:0] up_drp_rdata_hold = 'd0; + reg up_clk_sel = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == 6'h00) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == 6'h00) ? up_rreq : 1'b0; + + assign clk_sel = ~up_clk_sel; + + // processor write interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_mmcm_preset <= 1'd1; + up_wack <= 'd0; + up_scratch <= 'd0; + up_mmcm_resetn <= 'd0; + up_resetn <= 'd0; + up_drp_sel <= 'd0; + up_drp_wr <= 'd0; + up_drp_status <= 'd0; + up_drp_rwn <= 'd0; + up_drp_addr <= 'd0; + up_drp_wdata <= 'd0; + up_drp_rdata_hold <= 'd0; + up_clk_sel <= 'd0; + end else begin + up_mmcm_preset <= ~up_mmcm_resetn; + up_wack <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h02)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h10)) begin + up_mmcm_resetn <= up_wdata[1]; + up_resetn <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h11)) begin + up_clk_sel <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_sel <= 1'b1; + up_drp_wr <= ~up_wdata[28]; + end else begin + up_drp_sel <= 1'b0; + up_drp_wr <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_status <= 1'b1; + end else if (up_drp_ready == 1'b1) begin + up_drp_status <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_rwn <= up_wdata[28]; + up_drp_addr <= up_wdata[27:16]; + up_drp_wdata <= up_wdata[15:0]; + end + if (up_drp_ready == 1'b1) begin + up_drp_rdata_hold <= up_drp_rdata; + end + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_rack <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[7:0]) + 8'h00: up_rdata <= PCORE_VERSION; + 8'h01: up_rdata <= ID; + 8'h02: up_rdata <= up_scratch; + 8'h10: up_rdata <= {30'd0, up_mmcm_resetn, up_resetn}; + 8'h11: up_rdata <= {31'd0, up_clk_sel}; + 8'h17: up_rdata <= {31'd0, up_drp_locked}; + 8'h1c: up_rdata <= {3'd0, up_drp_rwn, up_drp_addr, up_drp_wdata}; + 8'h1d: up_rdata <= {14'd0, up_drp_locked, up_drp_status, up_drp_rdata_hold}; + default: up_rdata <= 0; + endcase + end else begin + up_rdata <= 32'd0; + end + end + end + + // resets + + ad_rst i_mmcm_rst_reg (.rst_async(up_mmcm_preset), .clk(up_clk), .rstn(), .rst(mmcm_rst)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_clock_mon.v b/src/adi/hdl/library/common/up_clock_mon.v new file mode 100644 index 00000000..01a8258c --- /dev/null +++ b/src/adi/hdl/library/common/up_clock_mon.v @@ -0,0 +1,146 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_clock_mon #( + parameter TOTAL_WIDTH = 32 +) ( + + // processor interface + + input up_rstn, + input up_clk, + output reg [TOTAL_WIDTH-1:0] up_d_count, + + // device interface + + input d_rst, + input d_clk); + + // internal registers + + reg [15:0] up_count = 'd1; + reg up_count_run = 'd0; + reg up_count_running_m1 = 'd0; + reg up_count_running_m2 = 'd0; + reg up_count_running_m3 = 'd0; + reg d_count_run_m1 = 'd0; + reg d_count_run_m2 = 'd0; + reg d_count_run_m3 = 'd0; + reg [TOTAL_WIDTH:0] d_count = 'd0; + + // internal signals + + wire up_count_capture_s; + wire d_count_reset_s; + + // processor reference + + // Capture on the falling edge of running + assign up_count_capture_s = up_count_running_m3 == 1'b1 && up_count_running_m2 == 1'b0; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_count_running_m1 <= 1'b0; + up_count_running_m2 <= 1'b0; + up_count_running_m3 <= 1'b0; + end else begin + up_count_running_m1 <= d_count_run_m3; + up_count_running_m2 <= up_count_running_m1; + up_count_running_m3 <= up_count_running_m2; + end + end + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_d_count <= 'd0; + up_count_run <= 1'b0; + end else begin + if (up_count_running_m3 == 1'b0) begin + up_count_run <= 1'b1; + end else if (up_count == 'h00) begin + up_count_run <= 1'b0; + end + + if (up_count_capture_s == 1'b1) begin + up_d_count <= d_count[TOTAL_WIDTH-1:0]; + end else if (up_count == 'h00 && up_count_run != up_count_running_m3) begin + up_d_count <= 'h00; + end + end + end + + always @(posedge up_clk) begin + if (up_count_run == 1'b0 && up_count_running_m3 == 1'b0) begin + up_count <= 'h01; + end else begin + up_count <= up_count + 1'b1; + end + end + + // device free running + + // Reset on the rising edge of run + assign d_count_reset_s = d_count_run_m3 == 1'b0 && d_count_run_m2 == 1'b1; + + always @(posedge d_clk or posedge d_rst) begin + if (d_rst == 1'b1) begin + d_count_run_m1 <= 1'b0; + d_count_run_m2 <= 1'b0; + d_count_run_m3 <= 1'b0; + end else begin + d_count_run_m1 <= up_count_run; + d_count_run_m2 <= d_count_run_m1; + d_count_run_m3 <= d_count_run_m2; + end + end + + always @(posedge d_clk) begin + if (d_count_reset_s == 1'b1) begin + d_count <= 'h00; + end else if (d_count_run_m3 == 1'b1) begin + if (d_count[TOTAL_WIDTH] == 1'b0) begin + d_count <= d_count + 1'b1; + end else begin + d_count <= {TOTAL_WIDTH+1{1'b1}}; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_dac_channel.v b/src/adi/hdl/library/common/up_dac_channel.v new file mode 100644 index 00000000..8c20ad7a --- /dev/null +++ b/src/adi/hdl/library/common/up_dac_channel.v @@ -0,0 +1,430 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_dac_channel #( + + // parameters + + parameter COMMON_ID = 6'h11, + parameter CHANNEL_ID = 4'h0, + parameter DDS_DISABLE = 0, + parameter USERPORTS_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 0) ( + + // dac interface + + input dac_clk, + input dac_rst, + output [15:0] dac_dds_scale_1, + output [15:0] dac_dds_init_1, + output [15:0] dac_dds_incr_1, + output [15:0] dac_dds_scale_2, + output [15:0] dac_dds_init_2, + output [15:0] dac_dds_incr_2, + output [15:0] dac_pat_data_1, + output [15:0] dac_pat_data_2, + output [ 3:0] dac_data_sel, + output [ 1:0] dac_iq_mode, + output dac_iqcor_enb, + output [15:0] dac_iqcor_coeff_1, + output [15:0] dac_iqcor_coeff_2, + + // user controls + + output up_usr_datatype_be, + output up_usr_datatype_signed, + output [ 7:0] up_usr_datatype_shift, + output [ 7:0] up_usr_datatype_total_bits, + output [ 7:0] up_usr_datatype_bits, + output [15:0] up_usr_interpolation_m, + output [15:0] up_usr_interpolation_n, + input dac_usr_datatype_be, + input dac_usr_datatype_signed, + input [ 7:0] dac_usr_datatype_shift, + input [ 7:0] dac_usr_datatype_total_bits, + input [ 7:0] dac_usr_datatype_bits, + input [15:0] dac_usr_interpolation_m, + input [15:0] dac_usr_interpolation_n, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack); + + // internal registers + + reg up_wack_int = 'd0; + reg [15:0] up_dac_dds_scale_1 = 'd0; + reg [15:0] up_dac_dds_init_1 = 'd0; + reg [15:0] up_dac_dds_incr_1 = 'd0; + reg [15:0] up_dac_dds_scale_2 = 'd0; + reg [15:0] up_dac_dds_init_2 = 'd0; + reg [15:0] up_dac_dds_incr_2 = 'd0; + reg [15:0] up_dac_pat_data_2 = 'd0; + reg [15:0] up_dac_pat_data_1 = 'd0; + reg up_dac_iqcor_enb = 'd0; + reg up_dac_lb_enb = 'd0; + reg up_dac_pn_enb = 'd0; + reg [ 3:0] up_dac_data_sel = 'd0; + reg [15:0] up_dac_iqcor_coeff_1 = 'd0; + reg [15:0] up_dac_iqcor_coeff_2 = 'd0; + reg up_usr_datatype_be_int = 'd0; + reg up_usr_datatype_signed_int = 'd0; + reg [ 7:0] up_usr_datatype_shift_int = 'd0; + reg [ 7:0] up_usr_datatype_total_bits_int = 'd0; + reg [ 7:0] up_usr_datatype_bits_int = 'd0; + reg [15:0] up_usr_interpolation_m_int = 'd0; + reg [15:0] up_usr_interpolation_n_int = 'd0; + reg [ 1:0] up_dac_iq_mode = 'd0; + reg up_rack_int = 'd0; + reg [31:0] up_rdata_int = 'd0; + reg [15:0] up_dac_dds_scale_tc_1 = 'd0; + reg [15:0] up_dac_dds_scale_tc_2 = 'd0; + reg [15:0] up_dac_iqcor_coeff_tc_1 = 'd0; + reg [15:0] up_dac_iqcor_coeff_tc_2 = 'd0; + reg [ 3:0] up_dac_data_sel_m = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + + // 2's complement function + + function [15:0] sm2tc; + input [15:0] din; + reg [15:0] dp; + reg [15:0] dn; + reg [15:0] dout; + begin + dp = {1'b0, din[14:0]}; + dn = ~dp + 1'b1; + dout = (din[15] == 1'b1) ? dn : dp; + sm2tc = dout; + end + endfunction + + // decode block select + + assign up_wreq_s = ((up_waddr[13:8] == COMMON_ID) && (up_waddr[7:4] == CHANNEL_ID)) ? up_wreq : 1'b0; + assign up_rreq_s = ((up_raddr[13:8] == COMMON_ID) && (up_raddr[7:4] == CHANNEL_ID)) ? up_rreq : 1'b0; + + // processor write interface + + assign up_wack = up_wack_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_wack_int <= 'd0; + end else begin + up_wack_int <= up_wreq_s; + end + end + + generate + if (DDS_DISABLE == 1) begin + always @(posedge up_clk) begin + up_dac_dds_scale_1 <= 'd0; + up_dac_dds_init_1 <= 'd0; + up_dac_dds_incr_1 <= 'd0; + up_dac_dds_scale_2 <= 'd0; + up_dac_dds_init_2 <= 'd0; + up_dac_dds_incr_2 <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_dds_scale_1 <= 'd0; + up_dac_dds_init_1 <= 'd0; + up_dac_dds_incr_1 <= 'd0; + up_dac_dds_scale_2 <= 'd0; + up_dac_dds_init_2 <= 'd0; + up_dac_dds_incr_2 <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin + up_dac_dds_scale_1 <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h1)) begin + up_dac_dds_init_1 <= up_wdata[31:16]; + up_dac_dds_incr_1 <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h2)) begin + up_dac_dds_scale_2 <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h3)) begin + up_dac_dds_init_2 <= up_wdata[31:16]; + up_dac_dds_incr_2 <= up_wdata[15:0]; + end + end + end + end + endgenerate + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_pat_data_2 <= 'd0; + up_dac_pat_data_1 <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h4)) begin + up_dac_pat_data_2 <= up_wdata[31:16]; + up_dac_pat_data_1 <= up_wdata[15:0]; + end + end + end + + generate + if (IQCORRECTION_DISABLE == 1) begin + always @(posedge up_clk) begin + up_dac_iqcor_enb <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_iqcor_enb <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h5)) begin + up_dac_iqcor_enb <= up_wdata[2]; + end + end + end + end + endgenerate + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_lb_enb <= 'd0; + up_dac_pn_enb <= 'd0; + up_dac_data_sel <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h5)) begin + up_dac_lb_enb <= up_wdata[1]; + up_dac_pn_enb <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h6)) begin + up_dac_data_sel <= up_wdata[3:0]; + end + end + end + + generate + if (IQCORRECTION_DISABLE == 1) begin + always @(posedge up_clk) begin + up_dac_iqcor_coeff_1 <= 'd0; + up_dac_iqcor_coeff_2 <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_iqcor_coeff_1 <= 'd0; + up_dac_iqcor_coeff_2 <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h7)) begin + up_dac_iqcor_coeff_1 <= up_wdata[31:16]; + up_dac_iqcor_coeff_2 <= up_wdata[15:0]; + end + end + end + end + endgenerate + + assign up_usr_datatype_be = up_usr_datatype_be_int; + assign up_usr_datatype_signed = up_usr_datatype_signed_int; + assign up_usr_datatype_shift = up_usr_datatype_shift_int; + assign up_usr_datatype_total_bits = up_usr_datatype_total_bits_int; + assign up_usr_datatype_bits = up_usr_datatype_bits_int; + assign up_usr_interpolation_m = up_usr_interpolation_m_int; + assign up_usr_interpolation_n = up_usr_interpolation_n_int; + + generate + if (USERPORTS_DISABLE == 1) begin + always @(posedge up_clk) begin + up_usr_datatype_be_int <= 'd0; + up_usr_datatype_signed_int <= 'd0; + up_usr_datatype_shift_int <= 'd0; + up_usr_datatype_total_bits_int <= 'd0; + up_usr_datatype_bits_int <= 'd0; + up_usr_interpolation_m_int <= 'd0; + up_usr_interpolation_n_int <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_usr_datatype_be_int <= 'd0; + up_usr_datatype_signed_int <= 'd0; + up_usr_datatype_shift_int <= 'd0; + up_usr_datatype_total_bits_int <= 'd0; + up_usr_datatype_bits_int <= 'd0; + up_usr_interpolation_m_int <= 'd0; + up_usr_interpolation_n_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h8)) begin + up_usr_datatype_be_int <= up_wdata[25]; + up_usr_datatype_signed_int <= up_wdata[24]; + up_usr_datatype_shift_int <= up_wdata[23:16]; + up_usr_datatype_total_bits_int <= up_wdata[15:8]; + up_usr_datatype_bits_int <= up_wdata[7:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h9)) begin + up_usr_interpolation_m_int <= up_wdata[31:16]; + up_usr_interpolation_n_int <= up_wdata[15:0]; + end + end + end + end + endgenerate + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_iq_mode <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'ha)) begin + up_dac_iq_mode <= up_wdata[1:0]; + end + end + end + + // processor read interface + + assign up_rack = up_rack_int; + assign up_rdata = up_rdata_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + end else begin + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[3:0]) + 4'h0: up_rdata_int <= { 16'd0, up_dac_dds_scale_1}; + 4'h1: up_rdata_int <= { up_dac_dds_init_1, up_dac_dds_incr_1}; + 4'h2: up_rdata_int <= { 16'd0, up_dac_dds_scale_2}; + 4'h3: up_rdata_int <= { up_dac_dds_init_2, up_dac_dds_incr_2}; + 4'h4: up_rdata_int <= { up_dac_pat_data_2, up_dac_pat_data_1}; + 4'h5: up_rdata_int <= { 29'd0, up_dac_iqcor_enb, up_dac_lb_enb, up_dac_pn_enb}; + 4'h6: up_rdata_int <= { 28'd0, up_dac_data_sel_m}; + 4'h7: up_rdata_int <= { up_dac_iqcor_coeff_1, up_dac_iqcor_coeff_2}; + 4'h8: up_rdata_int <= { 6'd0, dac_usr_datatype_be, dac_usr_datatype_signed, + dac_usr_datatype_shift, dac_usr_datatype_total_bits, + dac_usr_datatype_bits}; + 4'h9: up_rdata_int <= { dac_usr_interpolation_m, dac_usr_interpolation_n}; + 4'ha: up_rdata_int <= { 30'd0, up_dac_iq_mode}; + default: up_rdata_int <= 0; + endcase + end else begin + up_rdata_int <= 32'd0; + end + end + end + + // change coefficients to 2's complements + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_dds_scale_tc_1 <= 16'd0; + up_dac_dds_scale_tc_2 <= 16'd0; + up_dac_iqcor_coeff_tc_1 <= 16'd0; + up_dac_iqcor_coeff_tc_2 <= 16'd0; + end else begin + up_dac_dds_scale_tc_1 <= sm2tc(up_dac_dds_scale_1); + up_dac_dds_scale_tc_2 <= sm2tc(up_dac_dds_scale_2); + up_dac_iqcor_coeff_tc_1 <= sm2tc(up_dac_iqcor_coeff_1); + up_dac_iqcor_coeff_tc_2 <= sm2tc(up_dac_iqcor_coeff_2); + end + end + + // backward compatibility + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_data_sel_m <= 4'd0; + end else begin + case ({up_dac_lb_enb, up_dac_pn_enb}) + 2'b10: up_dac_data_sel_m <= 4'h8; + 2'b01: up_dac_data_sel_m <= 4'h9; + default: up_dac_data_sel_m <= up_dac_data_sel; + endcase + end + end + + // dac control & status + + up_xfer_cntrl #(.DATA_WIDTH(167)) i_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_dac_iq_mode, + up_dac_iqcor_enb, + up_dac_iqcor_coeff_tc_1, + up_dac_iqcor_coeff_tc_2, + up_dac_dds_scale_tc_1, + up_dac_dds_init_1, + up_dac_dds_incr_1, + up_dac_dds_scale_tc_2, + up_dac_dds_init_2, + up_dac_dds_incr_2, + up_dac_pat_data_1, + up_dac_pat_data_2, + up_dac_data_sel_m}), + .up_xfer_done (), + .d_rst (dac_rst), + .d_clk (dac_clk), + .d_data_cntrl ({ dac_iq_mode, + dac_iqcor_enb, + dac_iqcor_coeff_1, + dac_iqcor_coeff_2, + dac_dds_scale_1, + dac_dds_init_1, + dac_dds_incr_1, + dac_dds_scale_2, + dac_dds_init_2, + dac_dds_incr_2, + dac_pat_data_1, + dac_pat_data_2, + dac_data_sel})); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_dac_common.v b/src/adi/hdl/library/common/up_dac_common.v new file mode 100644 index 00000000..55ff8726 --- /dev/null +++ b/src/adi/hdl/library/common/up_dac_common.v @@ -0,0 +1,479 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_dac_common #( + + // parameters + + parameter ID = 0, + parameter CONFIG = 0, + parameter CLK_EDGE_SEL = 1'b0, + parameter COMMON_ID = 6'h10, + parameter DRP_DISABLE = 0, + parameter USERPORTS_DISABLE = 0, + parameter GPIO_DISABLE = 0) ( + + // mmcm reset + + output mmcm_rst, + + // dac interface + + input dac_clk, + output dac_rst, + output dac_sync, + output dac_frame, + output dac_clksel, + output dac_par_type, + output dac_par_enb, + output dac_r1_mode, + output dac_datafmt, + output [15:0] dac_datarate, + input dac_status, + input dac_status_unf, + input [31:0] dac_clk_ratio, + output up_dac_ce, + input [31:0] up_pps_rcounter, + input up_pps_status, + output reg up_pps_irq_mask, + + // drp interface + + output up_drp_sel, + output up_drp_wr, + output [11:0] up_drp_addr, + output [31:0] up_drp_wdata, + input [31:0] up_drp_rdata, + input up_drp_ready, + input up_drp_locked, + + // user channel control + + output [ 7:0] up_usr_chanmax, + input [ 7:0] dac_usr_chanmax, + input [31:0] up_dac_gpio_in, + output [31:0] up_dac_gpio_out, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack); + + // parameters + + localparam VERSION = 32'h00090062; + + // internal registers + + reg up_core_preset = 'd1; + reg up_mmcm_preset = 'd1; + reg up_wack_int = 'd0; + reg [31:0] up_scratch = 'd0; + reg up_dac_clk_enb_int = 'd0; + reg up_dac_clk_enb = 'd0; + reg up_mmcm_resetn = 'd0; + reg up_resetn = 'd0; + reg up_dac_sync = 'd0; + reg up_dac_par_type = 'd0; + reg up_dac_par_enb = 'd0; + reg up_dac_r1_mode = 'd0; + reg up_dac_datafmt = 'd0; + reg [15:0] up_dac_datarate = 'd0; + reg up_dac_frame = 'd0; + reg up_dac_clksel = CLK_EDGE_SEL; + reg up_status_unf = 'd0; + reg [ 7:0] up_usr_chanmax_int = 'd0; + reg [31:0] up_dac_gpio_out_int = 'd0; + reg [31:0] up_timer = 'd0; + reg up_rack_int = 'd0; + reg [31:0] up_rdata_int = 'd0; + reg dac_sync_d = 'd0; + reg dac_sync_2d = 'd0; + reg [ 5:0] dac_sync_count = 'd0; + reg dac_sync_int = 'd0; + reg dac_frame_d = 'd0; + reg dac_frame_2d = 'd0; + reg dac_frame_int = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire up_xfer_done_s; + wire up_status_s; + wire up_status_unf_s; + wire dac_sync_s; + wire dac_frame_s; + wire [31:0] up_dac_clk_count_s; + wire up_drp_status_s; + wire up_drp_rwn_s; + wire [31:0] up_drp_rdata_hold_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == COMMON_ID) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == COMMON_ID) ? up_rreq : 1'b0; + + assign up_dac_ce = up_dac_clk_enb_int; + + // processor write interface + + assign up_wack = up_wack_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_core_preset <= 1'd1; + up_mmcm_preset <= 1'd1; + up_wack_int <= 'd0; + up_scratch <= 'd0; + up_dac_clk_enb_int <= 'd1; + up_dac_clk_enb <= 'd0; + up_mmcm_resetn <= 'd0; + up_resetn <= 'd0; + up_dac_sync <= 'd0; + up_dac_par_type <= 'd0; + up_dac_par_enb <= 'd0; + up_dac_r1_mode <= 'd0; + up_dac_datafmt <= 'd0; + up_dac_datarate <= 'd0; + up_dac_frame <= 'd0; + up_dac_clksel <= CLK_EDGE_SEL; + up_pps_irq_mask <= 1'b1; + end else begin + up_dac_clk_enb_int <= ~up_dac_clk_enb; + up_core_preset <= ~up_resetn; + up_mmcm_preset <= ~up_mmcm_resetn; + up_wack_int <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h02)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h04)) begin + up_pps_irq_mask <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h10)) begin + up_dac_clk_enb <= up_wdata[2]; + up_mmcm_resetn <= up_wdata[1]; + up_resetn <= up_wdata[0]; + end + if (up_dac_sync == 1'b1) begin + if (up_xfer_done_s == 1'b1) begin + up_dac_sync <= 1'b0; + end + end else if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h11)) begin + up_dac_sync <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h12)) begin + up_dac_par_type <= up_wdata[7]; + up_dac_par_enb <= up_wdata[6]; + up_dac_r1_mode <= up_wdata[5]; + up_dac_datafmt <= up_wdata[4]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h13)) begin + up_dac_datarate <= up_wdata[15:0]; + end + if (up_dac_frame == 1'b1) begin + if (up_xfer_done_s == 1'b1) begin + up_dac_frame <= 1'b0; + end + end else if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h14)) begin + up_dac_frame <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h18)) begin + up_dac_clksel <= up_wdata[0]; + end + end + end + + generate + if (DRP_DISABLE == 1) begin + + assign up_drp_sel = 'd0; + assign up_drp_wr = 'd0; + assign up_drp_status_s = 'd0; + assign up_drp_rwn_s = 'd0; + assign up_drp_addr = 'd0; + assign up_drp_wdata = 'd0; + assign up_drp_rdata_hold_s = 'd0; + + end else begin + + reg up_drp_sel_int = 'd0; + reg up_drp_wr_int = 'd0; + reg up_drp_status_int = 'd0; + reg up_drp_rwn_int = 'd0; + reg [11:0] up_drp_addr_int = 'd0; + reg [31:0] up_drp_wdata_int = 'd0; + reg [31:0] up_drp_rdata_hold_int = 'd0; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_drp_sel_int <= 'd0; + up_drp_wr_int <= 'd0; + up_drp_status_int <= 'd0; + up_drp_rwn_int <= 'd0; + up_drp_addr_int <= 'd0; + up_drp_wdata_int <= 'd0; + up_drp_rdata_hold_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_sel_int <= 1'b1; + up_drp_wr_int <= ~up_wdata[28]; + end else begin + up_drp_sel_int <= 1'b0; + up_drp_wr_int <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_status_int <= 1'b1; + end else if (up_drp_ready == 1'b1) begin + up_drp_status_int <= 1'b0; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1c)) begin + up_drp_rwn_int <= up_wdata[28]; + up_drp_addr_int <= up_wdata[27:16]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h1e)) begin + up_drp_wdata_int <= up_wdata; + end + if (up_drp_ready == 1'b1) begin + up_drp_rdata_hold_int <= up_drp_rdata; + end + end + end + + assign up_drp_sel = up_drp_sel_int; + assign up_drp_wr = up_drp_wr_int; + assign up_drp_status_s = up_drp_status_int; + assign up_drp_rwn_s = up_drp_rwn_int; + assign up_drp_addr = up_drp_addr_int; + assign up_drp_wdata = up_drp_wdata_int; + assign up_drp_rdata_hold_s = up_drp_rdata_hold_int; + + end + endgenerate + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_status_unf <= 'd0; + end else begin + if (up_status_unf_s == 1'b1) begin + up_status_unf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h22)) begin + up_status_unf <= up_status_unf & ~up_wdata[0]; + end + end + end + + assign up_usr_chanmax = up_usr_chanmax_int; + + generate + if (USERPORTS_DISABLE == 1) begin + always @(posedge up_clk) begin + up_usr_chanmax_int <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_usr_chanmax_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h28)) begin + up_usr_chanmax_int <= up_wdata[7:0]; + end + end + end + end + endgenerate + + assign up_dac_gpio_out = up_dac_gpio_out_int; + + generate + if (GPIO_DISABLE == 1) begin + always @(posedge up_clk) begin + up_dac_gpio_out_int <= 'd0; + end + end else begin + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_dac_gpio_out_int <= 'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h2f)) begin + up_dac_gpio_out_int <= up_wdata; + end + end + end + end + endgenerate + + // timer with premature termination + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_timer <= 32'd0; + end else begin + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h40)) begin + up_timer <= up_wdata; + end else if (up_timer > 0) begin + up_timer <= up_timer - 1'b1; + end + end + end + + // processor read interface + + assign up_rack = up_rack_int; + assign up_rdata = up_rdata_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + end else begin + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[7:0]) + 8'h00: up_rdata_int <= VERSION; + 8'h01: up_rdata_int <= ID; + 8'h02: up_rdata_int <= up_scratch; + 8'h03: up_rdata_int <= CONFIG; + 8'h10: up_rdata_int <= {29'd0, up_dac_clk_enb, up_mmcm_resetn, up_resetn}; + 8'h11: up_rdata_int <= {31'd0, up_dac_sync}; + 8'h12: up_rdata_int <= {24'd0, up_dac_par_type, up_dac_par_enb, up_dac_r1_mode, + up_dac_datafmt, 4'd0}; + 8'h13: up_rdata_int <= {16'd0, up_dac_datarate}; + 8'h14: up_rdata_int <= {31'd0, up_dac_frame}; + 8'h15: up_rdata_int <= up_dac_clk_count_s; + 8'h16: up_rdata_int <= dac_clk_ratio; + 8'h17: up_rdata_int <= {31'd0, up_status_s}; + 8'h18: up_rdata_int <= {31'd0, up_dac_clksel}; + 8'h1c: up_rdata_int <= {3'd0, up_drp_rwn_s, up_drp_addr, 16'b0}; + 8'h1d: up_rdata_int <= {14'd0, up_drp_locked, up_drp_status_s, 16'b0}; + 8'h1e: up_rdata_int <= up_drp_wdata; + 8'h1f: up_rdata_int <= up_drp_rdata_hold_s; + 8'h22: up_rdata_int <= {31'd0, up_status_unf}; + 8'h28: up_rdata_int <= {24'd0, dac_usr_chanmax}; + 8'h2e: up_rdata_int <= up_dac_gpio_in; + 8'h2f: up_rdata_int <= up_dac_gpio_out_int; + 8'h30: up_rdata_int <= up_pps_rcounter; + 8'h31: up_rdata_int <= up_pps_status; + 8'h40: up_rdata_int <= up_timer; + default: up_rdata_int <= 0; + endcase + end else begin + up_rdata_int <= 32'd0; + end + end + end + + // resets + + ad_rst i_mmcm_rst_reg (.rst_async(up_mmcm_preset), .clk(up_clk), .rstn(), .rst(mmcm_rst)); + ad_rst i_core_rst_reg (.rst_async(up_core_preset), .clk(dac_clk), .rstn(), .rst(dac_rst)); + + // dac control & status + + up_xfer_cntrl #(.DATA_WIDTH(23)) i_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_dac_sync, + up_dac_clksel, + up_dac_frame, + up_dac_par_type, + up_dac_par_enb, + up_dac_r1_mode, + up_dac_datafmt, + up_dac_datarate}), + .up_xfer_done (up_xfer_done_s), + .d_rst (dac_rst), + .d_clk (dac_clk), + .d_data_cntrl ({ dac_sync_s, + dac_clksel, + dac_frame_s, + dac_par_type, + dac_par_enb, + dac_r1_mode, + dac_datafmt, + dac_datarate})); + + up_xfer_status #(.DATA_WIDTH(2)) i_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({up_status_s, + up_status_unf_s}), + .d_rst (dac_rst), + .d_clk (dac_clk), + .d_data_status ({ dac_status, + dac_status_unf})); + + // generate frame and enable + + assign dac_sync = dac_sync_int; + assign dac_frame = dac_frame_int; + + always @(posedge dac_clk) begin + dac_sync_d <= dac_sync_s; + dac_sync_2d <= dac_sync_d; + if (dac_sync_count[5] == 1'b1) begin + dac_sync_count <= dac_sync_count + 1'b1; + end else if ((dac_sync_d == 1'b1) && (dac_sync_2d == 1'b0)) begin + dac_sync_count <= 6'h20; + end + dac_sync_int <= dac_sync_count[5]; + dac_frame_d <= dac_frame_s; + dac_frame_2d <= dac_frame_d; + dac_frame_int <= dac_frame_d & ~dac_frame_2d; + end + + // dac clock monitor + + up_clock_mon i_clock_mon ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_d_count (up_dac_clk_count_s), + .d_rst (dac_rst), + .d_clk (dac_clk)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_delay_cntrl.v b/src/adi/hdl/library/common/up_delay_cntrl.v new file mode 100644 index 00000000..ae3210c1 --- /dev/null +++ b/src/adi/hdl/library/common/up_delay_cntrl.v @@ -0,0 +1,218 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_delay_cntrl #( + + // parameters + + parameter DISABLE = 0, + parameter INIT_DELAY = 0, + parameter DATA_WIDTH = 8, + parameter BASE_ADDRESS = 6'h02) ( + + // delay interface + + input delay_clk, + output delay_rst, + input delay_locked, + + // io interface + + output [(DATA_WIDTH-1):0] up_dld, + output [((DATA_WIDTH*5)-1):0] up_dwdata, + input [((DATA_WIDTH*5)-1):0] up_drdata, + + // processor interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack); + + generate + if (DISABLE == 1) begin + assign up_wack = 1'd0; + assign up_rack = 1'd0; + assign up_rdata = 32'd0; + + assign up_dld = 'd0; + assign up_dwdata = 'd0; + + assign delay_rst = 1'd0; + + end else begin + // internal registers + + reg up_preset = 'd0; + reg up_wack_int = 'd0; + reg up_rack_int = 'd0; + reg [31:0] up_rdata_int = 'd0; + reg up_dlocked_m1 = 'd0; + reg up_dlocked_m2 = 'd0; + reg up_dlocked_m3 = 'd0; + reg up_dlocked = 'd0; + reg [(DATA_WIDTH-1):0] up_dld_int = 'd0; + reg [((DATA_WIDTH*5)-1):0] up_dwdata_int = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire [ 4:0] up_rdata_s; + wire [(DATA_WIDTH-1):0] up_drdata4_s; + wire [(DATA_WIDTH-1):0] up_drdata3_s; + wire [(DATA_WIDTH-1):0] up_drdata2_s; + wire [(DATA_WIDTH-1):0] up_drdata1_s; + wire [(DATA_WIDTH-1):0] up_drdata0_s; + wire [(DATA_WIDTH-1):0] up_dld_s; + wire [((DATA_WIDTH*5)-1):0] up_dwdata_s; + wire [(DATA_WIDTH-1):0] up_dinit_s; + wire [((DATA_WIDTH*5)-1):0] up_dinitdata_s; + wire delay_rst_s; + + // variables + + genvar n; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == BASE_ADDRESS) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == BASE_ADDRESS) ? up_rreq : 1'b0; + assign up_rdata_s[4] = | up_drdata4_s; + assign up_rdata_s[3] = | up_drdata3_s; + assign up_rdata_s[2] = | up_drdata2_s; + assign up_rdata_s[1] = | up_drdata1_s; + assign up_rdata_s[0] = | up_drdata0_s; + + for (n = 0; n < DATA_WIDTH; n = n + 1) begin: g_drd + assign up_drdata4_s[n] = (up_raddr[7:0] == n) ? up_drdata[((n*5)+4)] : 1'd0; + assign up_drdata3_s[n] = (up_raddr[7:0] == n) ? up_drdata[((n*5)+3)] : 1'd0; + assign up_drdata2_s[n] = (up_raddr[7:0] == n) ? up_drdata[((n*5)+2)] : 1'd0; + assign up_drdata1_s[n] = (up_raddr[7:0] == n) ? up_drdata[((n*5)+1)] : 1'd0; + assign up_drdata0_s[n] = (up_raddr[7:0] == n) ? up_drdata[((n*5)+0)] : 1'd0; + end + + // processor interface + + assign up_wack = up_wack_int; + assign up_rack = up_rack_int; + assign up_rdata = up_rdata_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_preset <= 1'd1; + up_wack_int <= 'd0; + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + up_dlocked_m1 <= 'd0; + up_dlocked_m2 <= 'd0; + up_dlocked_m3 <= 'd0; + up_dlocked <= 'd0; + end else begin + up_preset <= 1'd0; + up_wack_int <= up_wreq_s; + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + if (up_dlocked == 1'b0) begin + up_rdata_int <= 32'hffffffff; + end else begin + up_rdata_int <= {27'd0, up_rdata_s}; + end + end else begin + up_rdata_int <= 32'd0; + end + up_dlocked_m1 <= delay_locked; + up_dlocked_m2 <= up_dlocked_m1; + up_dlocked_m3 <= up_dlocked_m2; + up_dlocked <= up_dlocked_m3; + end + end + + // init delay values (after delay locked) + + for (n = 0; n < DATA_WIDTH; n = n + 1) begin: g_dinit + assign up_dinit_s[n] = up_dlocked_m2 & ~up_dlocked_m3; + assign up_dinitdata_s[((n*5)+4):(n*5)] = INIT_DELAY; + end + + // write does not hold- read back what goes into effect. + + for (n = 0; n < DATA_WIDTH; n = n + 1) begin: g_dwr + assign up_dld_s[n] = (up_waddr[7:0] == n) ? up_wreq_s : 1'b0; + assign up_dwdata_s[((n*5)+4):(n*5)] = (up_waddr[7:0] == n) ? + up_wdata[4:0] : up_dwdata_int[((n*5)+4):(n*5)]; + end + + assign up_dld = up_dld_int; + assign up_dwdata = up_dwdata_int; + + always @(posedge up_clk) begin + if (up_rstn == 0) begin + up_dld_int <= 'd0; + up_dwdata_int <= 'd0; + end else begin + up_dld_int <= up_dld_s | up_dinit_s; + if ((up_dlocked_m2 == 1'b1) && (up_dlocked_m3 == 1'b0)) begin + up_dwdata_int <= up_dinitdata_s; + end else if (up_wreq_s == 1'b1) begin + up_dwdata_int <= up_dwdata_s; + end + end + end + + // resets + + assign delay_rst = delay_rst_s; + + ad_rst i_delay_rst_reg ( + .rst_async (up_preset), + .clk (delay_clk), + .rstn (), + .rst (delay_rst_s)); + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_hdmi_rx.v b/src/adi/hdl/library/common/up_hdmi_rx.v new file mode 100644 index 00000000..68955588 --- /dev/null +++ b/src/adi/hdl/library/common/up_hdmi_rx.v @@ -0,0 +1,286 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_hdmi_rx #( + + parameter ID = 0) ( + + // hdmi interface + + input hdmi_clk, + output hdmi_rst, + output hdmi_edge_sel, + output hdmi_bgr, + output hdmi_packed, + output hdmi_csc_bypass, + output [15:0] hdmi_vs_count, + output [15:0] hdmi_hs_count, + input hdmi_dma_ovf, + input hdmi_dma_unf, + input hdmi_tpm_oos, + input hdmi_vs_oos, + input hdmi_hs_oos, + input hdmi_vs_mismatch, + input hdmi_hs_mismatch, + input [15:0] hdmi_vs, + input [15:0] hdmi_hs, + input [31:0] hdmi_clk_ratio, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack); + + localparam PCORE_VERSION = 32'h00040063; + + // internal registers + + reg up_core_preset = 'd0; + reg up_resetn = 'd0; + reg [31:0] up_scratch = 'd0; + reg up_edge_sel = 'd0; + reg up_bgr = 'd0; + reg up_packed = 'd0; + reg up_csc_bypass = 'd0; + reg up_dma_ovf = 'd0; + reg up_dma_unf = 'd0; + reg up_tpm_oos = 'd0; + reg up_vs_oos = 'd0; + reg up_hs_oos = 'd0; + reg up_vs_mismatch = 'd0; + reg up_hs_mismatch = 'd0; + reg [15:0] up_vs_count = 'd0; + reg [15:0] up_hs_count = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire up_dma_ovf_s; + wire up_dma_unf_s; + wire up_vs_oos_s; + wire up_hs_oos_s; + wire up_vs_mismatch_s; + wire up_hs_mismatch_s; + wire [15:0] up_vs_s; + wire [15:0] up_hs_s; + wire [31:0] up_clk_count_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:12] == 2'd0) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:12] == 2'd0) ? up_rreq : 1'b0; + + // processor write interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_core_preset <= 1'd1; + up_resetn <= 'd0; + up_wack <= 'd0; + up_scratch <= 'd0; + up_edge_sel <= 'd0; + up_bgr <= 'd0; + up_packed <= 'd0; + up_csc_bypass <= 'd0; + up_dma_ovf <= 'd0; + up_dma_unf <= 'd0; + up_tpm_oos <= 'd0; + up_vs_oos <= 'd0; + up_hs_oos <= 'd0; + up_vs_mismatch <= 'd0; + up_hs_mismatch <= 'd0; + up_vs_count <= 'd0; + up_hs_count <= 'd0; + end else begin + up_wack <= up_wreq_s; + up_core_preset <= ~up_resetn; + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h002)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h010)) begin + up_resetn <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h011)) begin + up_edge_sel <= up_wdata[3]; + up_bgr <= up_wdata[2]; + up_packed <= up_wdata[1]; + up_csc_bypass <= up_wdata[0]; + end + if (up_dma_ovf_s == 1'b1) begin + up_dma_ovf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h018)) begin + up_dma_ovf <= up_dma_ovf & ~up_wdata[1]; + end + if (up_dma_unf_s == 1'b1) begin + up_dma_unf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h018)) begin + up_dma_unf <= up_dma_unf & ~up_wdata[0]; + end + if (up_tpm_oos_s == 1'b1) begin + up_tpm_oos <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h019)) begin + up_tpm_oos <= up_tpm_oos & ~up_wdata[1]; + end + if (up_vs_oos_s == 1'b1) begin + up_vs_oos <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h020)) begin + up_vs_oos <= up_vs_oos & ~up_wdata[3]; + end + if (up_hs_oos_s == 1'b1) begin + up_hs_oos <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h020)) begin + up_hs_oos <= up_hs_oos & ~up_wdata[2]; + end + if (up_vs_mismatch_s == 1'b1) begin + up_vs_mismatch <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h020)) begin + up_vs_mismatch <= up_vs_mismatch & ~up_wdata[1]; + end + if (up_hs_mismatch_s == 1'b1) begin + up_hs_mismatch <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h020)) begin + up_hs_mismatch <= up_hs_mismatch & ~up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h100)) begin + up_vs_count <= up_wdata[31:16]; + up_hs_count <= up_wdata[15:0]; + end + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_rack <= up_rreq_s; + if(up_rreq_s == 1'b1) begin + case (up_raddr[11:0]) + 12'h000: up_rdata <= PCORE_VERSION; + 12'h001: up_rdata <= ID; + 12'h002: up_rdata <= up_scratch; + 12'h010: up_rdata <= {31'h0, up_resetn}; + 12'h011: up_rdata <= {28'h0, up_edge_sel, up_bgr, up_packed, up_csc_bypass}; + 12'h015: up_rdata <= up_clk_count_s; + 12'h016: up_rdata <= hdmi_clk_ratio; + 12'h018: up_rdata <= {30'h0, up_dma_ovf, up_dma_unf}; + 12'h019: up_rdata <= {30'h0, up_tpm_oos, 1'b0}; + 12'h020: up_rdata <= {28'h0, up_vs_oos, up_hs_oos, + up_vs_mismatch, up_hs_mismatch}; + 12'h100: up_rdata <= {up_vs_count, up_hs_count}; + 12'h101: up_rdata <= {up_vs_s, up_hs_s}; + default: up_rdata <= 0; + endcase + end + end + end + + // resets + + ad_rst i_hdmi_rst_reg ( + .rst_async (up_core_preset), + .clk (hdmi_clk), + .rstn (), + .rst (hdmi_rst)); + + // hdmi control & status + + up_xfer_cntrl #(.DATA_WIDTH(36)) i_hdmi_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_edge_sel, + up_bgr, + up_packed, + up_csc_bypass, + up_vs_count, + up_hs_count}), + .up_xfer_done (), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk), + .d_data_cntrl ({ hdmi_edge_sel, + hdmi_bgr, + hdmi_packed, + hdmi_csc_bypass, + hdmi_vs_count, + hdmi_hs_count})); + + up_xfer_status #(.DATA_WIDTH(39)) i_hdmi_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({ up_dma_ovf_s, + up_dma_unf_s, + up_tpm_oos_s, + up_vs_oos_s, + up_hs_oos_s, + up_vs_mismatch_s, + up_hs_mismatch_s, + up_vs_s, + up_hs_s}), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk), + .d_data_status ({ hdmi_dma_ovf, + hdmi_dma_unf, + hdmi_tpm_oos, + hdmi_vs_oos, + hdmi_hs_oos, + hdmi_vs_mismatch, + hdmi_hs_mismatch, + hdmi_vs, + hdmi_hs})); + + up_clock_mon i_hdmi_clock_mon ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_d_count (up_clk_count_s), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_hdmi_tx.v b/src/adi/hdl/library/common/up_hdmi_tx.v new file mode 100644 index 00000000..219e34c0 --- /dev/null +++ b/src/adi/hdl/library/common/up_hdmi_tx.v @@ -0,0 +1,350 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_hdmi_tx #( + + parameter ID = 0) ( + + // hdmi interface + + input hdmi_clk, + output hdmi_rst, + output hdmi_csc_bypass, + output hdmi_ss_bypass, + output [ 1:0] hdmi_srcsel, + output [23:0] hdmi_const_rgb, + output [15:0] hdmi_hl_active, + output [15:0] hdmi_hl_width, + output [15:0] hdmi_hs_width, + output [15:0] hdmi_he_max, + output [15:0] hdmi_he_min, + output [15:0] hdmi_vf_active, + output [15:0] hdmi_vf_width, + output [15:0] hdmi_vs_width, + output [15:0] hdmi_ve_max, + output [15:0] hdmi_ve_min, + output [23:0] hdmi_clip_max, + output [23:0] hdmi_clip_min, + input hdmi_status, + input hdmi_tpm_oos, + input [31:0] hdmi_clk_ratio, + + // vdma interface + + input vdma_clk, + output vdma_rst, + input vdma_ovf, + input vdma_unf, + input vdma_tpm_oos, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack); + + localparam PCORE_VERSION = 32'h00040063; + + // internal registers + + reg up_core_preset = 'd0; + reg [31:0] up_scratch = 'd0; + reg up_resetn = 'd0; + reg up_csc_bypass = 'd0; + reg up_ss_bypass = 'd0; + reg [ 1:0] up_srcsel = 'd1; + reg [23:0] up_const_rgb = 'd0; + reg up_vdma_ovf = 'd0; + reg up_vdma_unf = 'd0; + reg up_hdmi_tpm_oos = 'd0; + reg up_vdma_tpm_oos = 'd0; + reg [15:0] up_hl_active = 'd0; + reg [15:0] up_hl_width = 'd0; + reg [15:0] up_hs_width = 'd0; + reg [15:0] up_he_max = 'd0; + reg [15:0] up_he_min = 'd0; + reg [15:0] up_vf_active = 'd0; + reg [15:0] up_vf_width = 'd0; + reg [15:0] up_vs_width = 'd0; + reg [15:0] up_ve_max = 'd0; + reg [15:0] up_ve_min = 'd0; + reg [23:0] up_clip_max = 'd0; + reg [23:0] up_clip_min = 'd0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + wire up_hdmi_status_s; + wire up_hdmi_tpm_oos_s; + wire [31:0] up_hdmi_clk_count_s; + wire up_vdma_ovf_s; + wire up_vdma_unf_s; + wire up_vdma_tpm_oos_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:12] == 2'd0) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:12] == 2'd0) ? up_rreq : 1'b0; + + // processor write interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_core_preset <= 1'd1; + up_wack <= 'd0; + up_scratch <= 'd0; + up_resetn <= 'd0; + up_csc_bypass <= 'd0; + up_ss_bypass <= 'd0; + up_srcsel <= 'd1; + up_const_rgb <= 'd0; + up_vdma_ovf <= 'd0; + up_vdma_unf <= 'd0; + up_hdmi_tpm_oos <= 'd0; + up_vdma_tpm_oos <= 'd0; + up_hl_active <= 'd0; + up_hl_width <= 'd0; + up_hs_width <= 'd0; + up_he_max <= 'd0; + up_he_min <= 'd0; + up_vf_active <= 'd0; + up_vf_width <= 'd0; + up_vs_width <= 'd0; + up_ve_max <= 'd0; + up_ve_min <= 'd0; + up_clip_max <= 24'hf0ebf0; + up_clip_min <= 24'h101010; + end else begin + up_core_preset <= ~up_resetn; + up_wack <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h002)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h010)) begin + up_resetn <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h011)) begin + up_ss_bypass <= up_wdata[2]; + up_csc_bypass <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h012)) begin + up_srcsel <= up_wdata[1:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h013)) begin + up_const_rgb <= up_wdata[23:0]; + end + if (up_vdma_ovf_s == 1'b1) begin + up_vdma_ovf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h018)) begin + up_vdma_ovf <= up_vdma_ovf & ~up_wdata[1]; + end + if (up_vdma_unf_s == 1'b1) begin + up_vdma_unf <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h018)) begin + up_vdma_unf <= up_vdma_unf & ~up_wdata[0]; + end + if (up_hdmi_tpm_oos_s == 1'b1) begin + up_hdmi_tpm_oos <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h019)) begin + up_hdmi_tpm_oos <= up_hdmi_tpm_oos & ~up_wdata[1]; + end + if (up_vdma_tpm_oos_s == 1'b1) begin + up_vdma_tpm_oos <= 1'b1; + end else if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h019)) begin + up_vdma_tpm_oos <= up_vdma_tpm_oos & ~up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h01a)) begin + up_clip_max <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h01b)) begin + up_clip_min <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h100)) begin + up_hl_active <= up_wdata[31:16]; + up_hl_width <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h101)) begin + up_hs_width <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h102)) begin + up_he_max <= up_wdata[31:16]; + up_he_min <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h110)) begin + up_vf_active <= up_wdata[31:16]; + up_vf_width <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h111)) begin + up_vs_width <= up_wdata[15:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[11:0] == 12'h112)) begin + up_ve_max <= up_wdata[31:16]; + up_ve_min <= up_wdata[15:0]; + end + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_rack <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[11:0]) + 12'h000: up_rdata <= PCORE_VERSION; + 12'h001: up_rdata <= ID; + 12'h002: up_rdata <= up_scratch; + 12'h010: up_rdata <= {31'd0, up_resetn}; + 12'h011: up_rdata <= {29'd0, up_ss_bypass, 1'b0, up_csc_bypass}; + 12'h012: up_rdata <= {30'd0, up_srcsel}; + 12'h013: up_rdata <= {8'd0, up_const_rgb}; + 12'h015: up_rdata <= up_hdmi_clk_count_s; + 12'h016: up_rdata <= hdmi_clk_ratio; + 12'h017: up_rdata <= {31'd0, up_hdmi_status_s}; + 12'h018: up_rdata <= {30'd0, up_vdma_ovf, up_vdma_unf}; + 12'h019: up_rdata <= {30'd0, up_hdmi_tpm_oos, up_vdma_tpm_oos}; + 12'h01a: up_rdata <= {8'd0, up_clip_max}; + 12'h01b: up_rdata <= {8'd0, up_clip_min}; + + 12'h100: up_rdata <= {up_hl_active, up_hl_width}; + 12'h101: up_rdata <= {16'd0, up_hs_width}; + 12'h102: up_rdata <= {up_he_max, up_he_min}; + 12'h110: up_rdata <= {up_vf_active, up_vf_width}; + 12'h111: up_rdata <= {16'd0, up_vs_width}; + 12'h112: up_rdata <= {up_ve_max, up_ve_min}; + default: up_rdata <= 0; + endcase + end else begin + up_rdata <= 32'd0; + end + end + end + + // resets + + ad_rst i_core_rst_reg (.rst_async(up_core_preset), .clk(hdmi_clk), .rstn(), .rst(hdmi_rst)); + ad_rst i_vdma_rst_reg (.rst_async(up_core_preset), .clk(vdma_clk), .rstn(), .rst(vdma_rst)); + + // hdmi control & status + + up_xfer_cntrl #(.DATA_WIDTH(236)) i_xfer_cntrl ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_cntrl ({ up_ss_bypass, + up_csc_bypass, + up_srcsel, + up_const_rgb, + up_hl_active, + up_hl_width, + up_hs_width, + up_he_max, + up_he_min, + up_vf_active, + up_vf_width, + up_vs_width, + up_ve_max, + up_ve_min, + up_clip_max, + up_clip_min}), + .up_xfer_done (), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk), + .d_data_cntrl ({ hdmi_ss_bypass, + hdmi_csc_bypass, + hdmi_srcsel, + hdmi_const_rgb, + hdmi_hl_active, + hdmi_hl_width, + hdmi_hs_width, + hdmi_he_max, + hdmi_he_min, + hdmi_vf_active, + hdmi_vf_width, + hdmi_vs_width, + hdmi_ve_max, + hdmi_ve_min, + hdmi_clip_max, + hdmi_clip_min})); + + up_xfer_status #(.DATA_WIDTH(2)) i_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({up_hdmi_status_s, + up_hdmi_tpm_oos_s}), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk), + .d_data_status ({ hdmi_status, + hdmi_tpm_oos})); + + // hdmi clock monitor + + up_clock_mon i_clock_mon ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_d_count (up_hdmi_clk_count_s), + .d_rst (hdmi_rst), + .d_clk (hdmi_clk)); + + // vdma control & status + + up_xfer_status #(.DATA_WIDTH(3)) i_vdma_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status ({up_vdma_ovf_s, + up_vdma_unf_s, + up_vdma_tpm_oos_s}), + .d_rst (vdma_rst), + .d_clk (vdma_clk), + .d_data_status ({ vdma_ovf, + vdma_unf, + vdma_tpm_oos})); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_pmod.v b/src/adi/hdl/library/common/up_pmod.v new file mode 100644 index 00000000..defe31cb --- /dev/null +++ b/src/adi/hdl/library/common/up_pmod.v @@ -0,0 +1,136 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_pmod #( + + parameter ID = 0) ( + + input pmod_clk, + output pmod_rst, + input [31:0] pmod_signal_freq, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack); + + localparam PCORE_VERSION = 32'h00010001; + + // internal registers + + reg [31:0] up_scratch = 'd0; + reg up_resetn = 'd0; + + // internal signals + + wire [31:0] up_pmod_signal_freq_s; + wire up_wreq_s; + wire up_rreq_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == 6'h00) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == 6'h00) ? up_rreq : 1'b0; + assign up_preset_s = ~up_resetn; + + // processor write interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_wack <= 'd0; + up_scratch <= 'd0; + up_resetn <= 'd0; + end else begin + up_wack <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h02)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h10)) begin + up_resetn <= up_wdata[0]; + end + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_rack <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[7:0]) + 8'h00: up_rdata <= PCORE_VERSION; + 8'h01: up_rdata <= ID; + 8'h02: up_rdata <= up_scratch; + 8'h03: up_rdata <= up_pmod_signal_freq_s; + 8'h10: up_rdata <= up_resetn; + default: up_rdata <= 0; + endcase + end else begin + up_rdata <= 32'd0; + end + end + end + + // resets + + ad_rst i_adc_rst_reg (.rst_async(up_preset_s), .clk(pmod_clk), .rstn(), .rst(pmod_rst)); + + // adc control & status + + up_xfer_status #(.DATA_WIDTH(32)) i_pmod_xfer_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status (up_pmod_signal_freq_s), + .d_rst (pmod_rst), + .d_clk (pmod_clk), + .d_data_status (pmod_signal_freq)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_tdd_cntrl.v b/src/adi/hdl/library/common/up_tdd_cntrl.v new file mode 100644 index 00000000..8715ac36 --- /dev/null +++ b/src/adi/hdl/library/common/up_tdd_cntrl.v @@ -0,0 +1,444 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +`timescale 1ns/100ps + +module up_tdd_cntrl #( + + parameter ID = 0) ( + + input clk, + input rst, + + //rf tdd interface control + + output tdd_enable, + output tdd_secondary, + output tdd_rx_only, + output tdd_tx_only, + output tdd_gated_rx_dmapath, + output tdd_gated_tx_dmapath, + output [ 7:0] tdd_burst_count, + output [23:0] tdd_counter_init, + output [23:0] tdd_frame_length, + output tdd_terminal_type, + output [23:0] tdd_vco_rx_on_1, + output [23:0] tdd_vco_rx_off_1, + output [23:0] tdd_vco_tx_on_1, + output [23:0] tdd_vco_tx_off_1, + output [23:0] tdd_rx_on_1, + output [23:0] tdd_rx_off_1, + output [23:0] tdd_rx_dp_on_1, + output [23:0] tdd_rx_dp_off_1, + output [23:0] tdd_tx_on_1, + output [23:0] tdd_tx_off_1, + output [23:0] tdd_tx_dp_on_1, + output [23:0] tdd_tx_dp_off_1, + output [23:0] tdd_vco_rx_on_2, + output [23:0] tdd_vco_rx_off_2, + output [23:0] tdd_vco_tx_on_2, + output [23:0] tdd_vco_tx_off_2, + output [23:0] tdd_rx_on_2, + output [23:0] tdd_rx_off_2, + output [23:0] tdd_rx_dp_on_2, + output [23:0] tdd_rx_dp_off_2, + output [23:0] tdd_tx_on_2, + output [23:0] tdd_tx_off_2, + output [23:0] tdd_tx_dp_on_2, + output [23:0] tdd_tx_dp_off_2, + + input [ 7:0] tdd_status, + + // bus interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack); + + localparam PCORE_VERSION = 32'h00010061; + + // internal registers + + reg [31:0] up_scratch = 32'h0; + + reg up_tdd_enable = 1'h0; + reg up_tdd_secondary = 1'h0; + reg up_tdd_rx_only = 1'h0; + reg up_tdd_tx_only = 1'h0; + reg up_tdd_gated_tx_dmapath = 1'h0; + reg up_tdd_gated_rx_dmapath = 1'h0; + reg up_tdd_terminal_type = 1'h0; + + reg [ 7:0] up_tdd_burst_count = 8'h0; + reg [23:0] up_tdd_counter_init = 24'h0; + reg [23:0] up_tdd_frame_length = 24'h0; + + reg [23:0] up_tdd_vco_rx_on_1 = 24'h0; + reg [23:0] up_tdd_vco_rx_off_1 = 24'h0; + reg [23:0] up_tdd_vco_tx_on_1 = 24'h0; + reg [23:0] up_tdd_vco_tx_off_1 = 24'h0; + reg [23:0] up_tdd_rx_on_1 = 24'h0; + reg [23:0] up_tdd_rx_off_1 = 24'h0; + reg [23:0] up_tdd_rx_dp_on_1 = 24'h0; + reg [23:0] up_tdd_rx_dp_off_1 = 24'h0; + reg [23:0] up_tdd_tx_on_1 = 24'h0; + reg [23:0] up_tdd_tx_off_1 = 24'h0; + reg [23:0] up_tdd_tx_dp_on_1 = 24'h0; + reg [23:0] up_tdd_tx_dp_off_1 = 24'h0; + reg [23:0] up_tdd_vco_rx_on_2 = 24'h0; + reg [23:0] up_tdd_vco_rx_off_2 = 24'h0; + reg [23:0] up_tdd_vco_tx_on_2 = 24'h0; + reg [23:0] up_tdd_vco_tx_off_2 = 24'h0; + reg [23:0] up_tdd_rx_on_2 = 24'h0; + reg [23:0] up_tdd_rx_off_2 = 24'h0; + reg [23:0] up_tdd_rx_dp_on_2 = 24'h0; + reg [23:0] up_tdd_rx_dp_off_2 = 24'h0; + reg [23:0] up_tdd_tx_on_2 = 24'h0; + reg [23:0] up_tdd_tx_off_2 = 24'h0; + reg [23:0] up_tdd_tx_dp_on_2 = 24'h0; + reg [23:0] up_tdd_tx_dp_off_2 = 24'h0; + + // internal signals + + wire up_wreq_s; + wire up_rreq_s; + + wire [ 7:0] up_tdd_status_s; + + // decode block select + + assign up_wreq_s = (up_waddr[13:8] == 6'h20) ? up_wreq : 1'b0; + assign up_rreq_s = (up_raddr[13:8] == 6'h20) ? up_rreq : 1'b0; + + // processor write interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_wack <= 1'h0; + up_scratch <= 32'h0; + up_tdd_enable <= 1'h0; + up_tdd_secondary <= 1'h0; + up_tdd_rx_only <= 1'h0; + up_tdd_tx_only <= 1'h0; + up_tdd_gated_tx_dmapath <= 1'h0; + up_tdd_gated_rx_dmapath <= 1'h0; + up_tdd_terminal_type <= 1'h0; + up_tdd_counter_init <= 24'h0; + up_tdd_frame_length <= 24'h0; + up_tdd_burst_count <= 8'h0; + up_tdd_vco_rx_on_1 <= 24'h0; + up_tdd_vco_rx_off_1 <= 24'h0; + up_tdd_vco_tx_on_1 <= 24'h0; + up_tdd_vco_tx_off_1 <= 24'h0; + up_tdd_rx_on_1 <= 24'h0; + up_tdd_rx_off_1 <= 24'h0; + up_tdd_rx_dp_on_1 <= 24'h0; + up_tdd_rx_dp_off_1 <= 24'h0; + up_tdd_tx_on_1 <= 24'h0; + up_tdd_tx_off_1 <= 24'h0; + up_tdd_tx_dp_on_1 <= 24'h0; + up_tdd_tx_dp_off_1 <= 24'h0; + up_tdd_vco_rx_on_2 <= 24'h0; + up_tdd_vco_rx_off_2 <= 24'h0; + up_tdd_vco_tx_on_2 <= 24'h0; + up_tdd_vco_tx_off_2 <= 24'h0; + up_tdd_rx_on_2 <= 24'h0; + up_tdd_rx_off_2 <= 24'h0; + up_tdd_rx_dp_on_2 <= 24'h0; + up_tdd_rx_dp_off_2 <= 24'h0; + up_tdd_tx_on_2 <= 24'h0; + up_tdd_tx_off_2 <= 24'h0; + up_tdd_tx_dp_on_2 <= 24'h0; + up_tdd_tx_dp_off_2 <= 24'h0; + end else begin + up_wack <= up_wreq_s; + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h02)) begin + up_scratch <= up_wdata; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h10)) begin + up_tdd_enable <= up_wdata[0]; + up_tdd_secondary <= up_wdata[1]; + up_tdd_rx_only <= up_wdata[2]; + up_tdd_tx_only <= up_wdata[3]; + up_tdd_gated_rx_dmapath <= up_wdata[4]; + up_tdd_gated_tx_dmapath <= up_wdata[5]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h11)) begin + up_tdd_burst_count <= up_wdata[7:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h12)) begin + up_tdd_counter_init <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h13)) begin + up_tdd_frame_length <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h14)) begin + up_tdd_terminal_type <= up_wdata[0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h20)) begin + up_tdd_vco_rx_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h21)) begin + up_tdd_vco_rx_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h22)) begin + up_tdd_vco_tx_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h23)) begin + up_tdd_vco_tx_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h24)) begin + up_tdd_rx_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h25)) begin + up_tdd_rx_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h26)) begin + up_tdd_tx_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h27)) begin + up_tdd_tx_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h28)) begin + up_tdd_rx_dp_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h29)) begin + up_tdd_rx_dp_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h2a)) begin + up_tdd_tx_dp_on_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h2b)) begin + up_tdd_tx_dp_off_1 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h30)) begin + up_tdd_vco_rx_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h31)) begin + up_tdd_vco_rx_off_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h32)) begin + up_tdd_vco_tx_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h33)) begin + up_tdd_vco_tx_off_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h34)) begin + up_tdd_rx_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h35)) begin + up_tdd_rx_off_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h36)) begin + up_tdd_tx_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h37)) begin + up_tdd_tx_off_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h38)) begin + up_tdd_rx_dp_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h39)) begin + up_tdd_rx_dp_off_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h3a)) begin + up_tdd_tx_dp_on_2 <= up_wdata[23:0]; + end + if ((up_wreq_s == 1'b1) && (up_waddr[7:0] == 8'h3b)) begin + up_tdd_tx_dp_off_2 <= up_wdata[23:0]; + end + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack <= 1'b0; + up_rdata <= 1'b0; + end else begin + up_rack <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr[7:0]) + 8'h00: up_rdata <= PCORE_VERSION; + 8'h01: up_rdata <= ID; + 8'h02: up_rdata <= up_scratch; + 8'h10: up_rdata <= {28'h0, up_tdd_gated_tx_dmapath, + up_tdd_gated_rx_dmapath, + up_tdd_tx_only, + up_tdd_rx_only, + up_tdd_secondary, + up_tdd_enable}; + 8'h11: up_rdata <= {24'h0, up_tdd_burst_count}; + 8'h12: up_rdata <= { 8'h0, up_tdd_counter_init}; + 8'h13: up_rdata <= { 8'h0, up_tdd_frame_length}; + 8'h14: up_rdata <= {31'h0, up_tdd_terminal_type}; + 8'h18: up_rdata <= {24'h0, up_tdd_status_s}; + 8'h20: up_rdata <= { 8'h0, up_tdd_vco_rx_on_1}; + 8'h21: up_rdata <= { 8'h0, up_tdd_vco_rx_off_1}; + 8'h22: up_rdata <= { 8'h0, up_tdd_vco_tx_on_1}; + 8'h23: up_rdata <= { 8'h0, up_tdd_vco_tx_off_1}; + 8'h24: up_rdata <= { 8'h0, up_tdd_rx_on_1}; + 8'h25: up_rdata <= { 8'h0, up_tdd_rx_off_1}; + 8'h26: up_rdata <= { 8'h0, up_tdd_tx_on_1}; + 8'h27: up_rdata <= { 8'h0, up_tdd_tx_off_1}; + 8'h28: up_rdata <= { 8'h0, up_tdd_rx_dp_on_1}; + 8'h29: up_rdata <= { 8'h0, up_tdd_rx_dp_off_1}; + 8'h2a: up_rdata <= { 8'h0, up_tdd_tx_dp_on_1}; + 8'h2b: up_rdata <= { 8'h0, up_tdd_tx_dp_off_1}; + 8'h30: up_rdata <= { 8'h0, up_tdd_vco_rx_on_2}; + 8'h31: up_rdata <= { 8'h0, up_tdd_vco_rx_off_2}; + 8'h32: up_rdata <= { 8'h0, up_tdd_vco_tx_on_2}; + 8'h33: up_rdata <= { 8'h0, up_tdd_vco_tx_off_2}; + 8'h34: up_rdata <= { 8'h0, up_tdd_rx_on_2}; + 8'h35: up_rdata <= { 8'h0, up_tdd_rx_off_2}; + 8'h36: up_rdata <= { 8'h0, up_tdd_tx_on_2}; + 8'h37: up_rdata <= { 8'h0, up_tdd_tx_off_2}; + 8'h38: up_rdata <= { 8'h0, up_tdd_rx_dp_on_2}; + 8'h39: up_rdata <= { 8'h0, up_tdd_rx_dp_off_2}; + 8'h3a: up_rdata <= { 8'h0, up_tdd_tx_dp_on_2}; + 8'h3b: up_rdata <= { 8'h0, up_tdd_tx_dp_off_2}; + default: up_rdata <= 32'h0; + endcase + end + end + end + + // rf tdd control signal CDC + + up_xfer_cntrl #(.DATA_WIDTH(15)) i_xfer_tdd_control ( + .up_rstn(up_rstn), + .up_clk(up_clk), + .up_data_cntrl({up_tdd_enable, + up_tdd_secondary, + up_tdd_rx_only, + up_tdd_tx_only, + up_tdd_gated_rx_dmapath, + up_tdd_gated_tx_dmapath, + up_tdd_burst_count, + up_tdd_terminal_type + }), + .up_xfer_done(), + .d_rst(rst), + .d_clk(clk), + .d_data_cntrl({tdd_enable, + tdd_secondary, + tdd_rx_only, + tdd_tx_only, + tdd_gated_rx_dmapath, + tdd_gated_tx_dmapath, + tdd_burst_count, + tdd_terminal_type + })); + + up_xfer_cntrl #(.DATA_WIDTH(624)) i_xfer_tdd_counter_values ( + .up_rstn(up_rstn), + .up_clk(up_clk), + .up_data_cntrl({up_tdd_counter_init, + up_tdd_frame_length, + up_tdd_vco_rx_on_1, + up_tdd_vco_rx_off_1, + up_tdd_vco_tx_on_1, + up_tdd_vco_tx_off_1, + up_tdd_rx_on_1, + up_tdd_rx_off_1, + up_tdd_tx_on_1, + up_tdd_tx_off_1, + up_tdd_rx_dp_on_1, + up_tdd_rx_dp_off_1, + up_tdd_tx_dp_on_1, + up_tdd_tx_dp_off_1, + up_tdd_vco_rx_on_2, + up_tdd_vco_rx_off_2, + up_tdd_vco_tx_on_2, + up_tdd_vco_tx_off_2, + up_tdd_rx_on_2, + up_tdd_rx_off_2, + up_tdd_tx_on_2, + up_tdd_tx_off_2, + up_tdd_rx_dp_on_2, + up_tdd_rx_dp_off_2, + up_tdd_tx_dp_on_2, + up_tdd_tx_dp_off_2 + }), + .up_xfer_done(), + .d_rst(rst), + .d_clk(clk), + .d_data_cntrl({tdd_counter_init, + tdd_frame_length, + tdd_vco_rx_on_1, + tdd_vco_rx_off_1, + tdd_vco_tx_on_1, + tdd_vco_tx_off_1, + tdd_rx_on_1, + tdd_rx_off_1, + tdd_tx_on_1, + tdd_tx_off_1, + tdd_rx_dp_on_1, + tdd_rx_dp_off_1, + tdd_tx_dp_on_1, + tdd_tx_dp_off_1, + tdd_vco_rx_on_2, + tdd_vco_rx_off_2, + tdd_vco_tx_on_2, + tdd_vco_tx_off_2, + tdd_rx_on_2, + tdd_rx_off_2, + tdd_tx_on_2, + tdd_tx_off_2, + tdd_rx_dp_on_2, + tdd_rx_dp_off_2, + tdd_tx_dp_on_2, + tdd_tx_dp_off_2 + })); + + up_xfer_status #(.DATA_WIDTH(8)) i_xfer_tdd_status ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_data_status (up_tdd_status_s), + .d_rst (rst), + .d_clk (clk), + .d_data_status (tdd_status)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_xfer_cntrl.v b/src/adi/hdl/library/common/up_xfer_cntrl.v new file mode 100644 index 00000000..3a6307cd --- /dev/null +++ b/src/adi/hdl/library/common/up_xfer_cntrl.v @@ -0,0 +1,126 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_xfer_cntrl #( + + parameter DATA_WIDTH = 8) ( + + // up interface + + input up_rstn, + input up_clk, + input [(DATA_WIDTH-1):0] up_data_cntrl, + output up_xfer_done, + + // device interface + + input d_rst, + input d_clk, + output [(DATA_WIDTH-1):0] d_data_cntrl); + + // internal registers + + reg up_xfer_state_m1 = 'd0; + reg up_xfer_state_m2 = 'd0; + reg up_xfer_state = 'd0; + reg [ 5:0] up_xfer_count = 'd0; + reg up_xfer_done_int = 'd0; + reg up_xfer_toggle = 'd0; + reg [(DATA_WIDTH-1):0] up_xfer_data = 'd0; + reg d_xfer_toggle_m1 = 'd0; + reg d_xfer_toggle_m2 = 'd0; + reg d_xfer_toggle_m3 = 'd0; + reg d_xfer_toggle = 'd0; + reg [(DATA_WIDTH-1):0] d_data_cntrl_int = 'd0; + + // internal signals + + wire up_xfer_enable_s; + wire d_xfer_toggle_s; + + // device control transfer + + assign up_xfer_done = up_xfer_done_int; + assign up_xfer_enable_s = up_xfer_state ^ up_xfer_toggle; + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_xfer_state_m1 <= 'd0; + up_xfer_state_m2 <= 'd0; + up_xfer_state <= 'd0; + up_xfer_count <= 'd0; + up_xfer_done_int <= 'd0; + up_xfer_toggle <= 'd0; + up_xfer_data <= 'd0; + end else begin + up_xfer_state_m1 <= d_xfer_toggle; + up_xfer_state_m2 <= up_xfer_state_m1; + up_xfer_state <= up_xfer_state_m2; + up_xfer_count <= up_xfer_count + 1'd1; + up_xfer_done_int <= (up_xfer_count == 6'd1) ? ~up_xfer_enable_s : 1'b0; + if ((up_xfer_count == 6'd1) && (up_xfer_enable_s == 1'b0)) begin + up_xfer_toggle <= ~up_xfer_toggle; + up_xfer_data <= up_data_cntrl; + end + end + end + + assign d_data_cntrl = d_data_cntrl_int; + assign d_xfer_toggle_s = d_xfer_toggle_m3 ^ d_xfer_toggle_m2; + + always @(posedge d_clk or posedge d_rst) begin + if (d_rst == 1'b1) begin + d_xfer_toggle_m1 <= 'd0; + d_xfer_toggle_m2 <= 'd0; + d_xfer_toggle_m3 <= 'd0; + d_xfer_toggle <= 'd0; + d_data_cntrl_int <= 'd0; + end else begin + d_xfer_toggle_m1 <= up_xfer_toggle; + d_xfer_toggle_m2 <= d_xfer_toggle_m1; + d_xfer_toggle_m3 <= d_xfer_toggle_m2; + d_xfer_toggle <= d_xfer_toggle_m3; + if (d_xfer_toggle_s == 1'b1) begin + d_data_cntrl_int <= up_xfer_data; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/up_xfer_status.v b/src/adi/hdl/library/common/up_xfer_status.v new file mode 100644 index 00000000..59c5f9f2 --- /dev/null +++ b/src/adi/hdl/library/common/up_xfer_status.v @@ -0,0 +1,128 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module up_xfer_status #( + + parameter DATA_WIDTH = 8) ( + + // up interface + + input up_rstn, + input up_clk, + output [(DATA_WIDTH-1):0] up_data_status, + + // device interface + + input d_rst, + input d_clk, + input [(DATA_WIDTH-1):0] d_data_status); + + // internal registers + + reg d_xfer_state_m1 = 'd0; + reg d_xfer_state_m2 = 'd0; + reg d_xfer_state = 'd0; + reg [ 5:0] d_xfer_count = 'd0; + reg d_xfer_toggle = 'd0; + reg [(DATA_WIDTH-1):0] d_xfer_data = 'd0; + reg [(DATA_WIDTH-1):0] d_acc_data = 'd0; + reg up_xfer_toggle_m1 = 'd0; + reg up_xfer_toggle_m2 = 'd0; + reg up_xfer_toggle_m3 = 'd0; + reg up_xfer_toggle = 'd0; + reg [(DATA_WIDTH-1):0] up_data_status_int = 'd0; + + // internal signals + + wire d_xfer_enable_s; + wire up_xfer_toggle_s; + + // device status transfer + + assign d_xfer_enable_s = d_xfer_state ^ d_xfer_toggle; + + always @(posedge d_clk or posedge d_rst) begin + if (d_rst == 1'b1) begin + d_xfer_state_m1 <= 'd0; + d_xfer_state_m2 <= 'd0; + d_xfer_state <= 'd0; + d_xfer_count <= 'd0; + d_xfer_toggle <= 'd0; + d_xfer_data <= 'd0; + d_acc_data <= 'd0; + end else begin + d_xfer_state_m1 <= up_xfer_toggle; + d_xfer_state_m2 <= d_xfer_state_m1; + d_xfer_state <= d_xfer_state_m2; + d_xfer_count <= d_xfer_count + 1'd1; + if ((d_xfer_count == 6'd1) && (d_xfer_enable_s == 1'b0)) begin + d_xfer_toggle <= ~d_xfer_toggle; + d_xfer_data <= d_acc_data; + end + if ((d_xfer_count == 6'd1) && (d_xfer_enable_s == 1'b0)) begin + d_acc_data <= d_data_status; + end else begin + d_acc_data <= d_acc_data | d_data_status; + end + end + end + + assign up_data_status = up_data_status_int; + assign up_xfer_toggle_s = up_xfer_toggle_m3 ^ up_xfer_toggle_m2; + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_xfer_toggle_m1 <= 'd0; + up_xfer_toggle_m2 <= 'd0; + up_xfer_toggle_m3 <= 'd0; + up_xfer_toggle <= 'd0; + up_data_status_int <= 'd0; + end else begin + up_xfer_toggle_m1 <= d_xfer_toggle; + up_xfer_toggle_m2 <= up_xfer_toggle_m1; + up_xfer_toggle_m3 <= up_xfer_toggle_m2; + up_xfer_toggle <= up_xfer_toggle_m3; + if (up_xfer_toggle_s == 1'b1) begin + up_data_status_int <= d_xfer_data; + end + end + end + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/common/util_axis_upscale.v b/src/adi/hdl/library/common/util_axis_upscale.v new file mode 100644 index 00000000..575070c8 --- /dev/null +++ b/src/adi/hdl/library/common/util_axis_upscale.v @@ -0,0 +1,98 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// + A simple AXI stream data upscale module, which can be used with devices +// with resolution which can not be aligned to a WORD (32 bits). Eg. 24 bits +// + It has the same control interface as the ad_datafmt module, which controls +// the data format inside a generic AXI converter core. +// + Supports multiple channels. Contains a single register stage. + +`timescale 1ns/100ps + +module util_axis_upscale # ( + + parameter NUM_OF_CHANNELS = 4, + parameter DATA_WIDTH = 24, + parameter UDATA_WIDTH = 32)( + + input clk, + input resetn, + + input s_axis_valid, + output reg s_axis_ready, + input [(NUM_OF_CHANNELS*DATA_WIDTH)-1:0] s_axis_data, + + output reg m_axis_valid, + input m_axis_ready, + output reg [(NUM_OF_CHANNELS*UDATA_WIDTH)-1:0] m_axis_data, + + input dfmt_enable, + input dfmt_type, + input dfmt_se); + + wire type_s; + wire signext_s; + wire sign_s; + wire [(NUM_OF_CHANNELS*UDATA_WIDTH)-1:0] data_out_s; + + localparam MSB_WIDTH = UDATA_WIDTH - DATA_WIDTH; + + assign type_s = dfmt_enable & dfmt_type; + assign signext_s = dfmt_enable & dfmt_se; + assign sign_s = signext_s & (type_s ^ s_axis_data[(DATA_WIDTH-1)]); + + genvar i; + generate + for (i=1; i <= NUM_OF_CHANNELS; i=i+1) begin + + assign data_out_s[(i*UDATA_WIDTH-1):(i*UDATA_WIDTH-MSB_WIDTH)] = {(MSB_WIDTH){sign_s}}; + assign data_out_s[((i-1)*UDATA_WIDTH+DATA_WIDTH-1)] = type_s ^ s_axis_data[(i*DATA_WIDTH-1)]; + assign data_out_s[((i-1)*UDATA_WIDTH+DATA_WIDTH-2):((i-1)*UDATA_WIDTH)] = s_axis_data[(i*DATA_WIDTH-2):((i-1)*DATA_WIDTH)]; + + end + endgenerate + + always @(posedge clk) begin + if (resetn == 1'b0) begin + m_axis_valid <= 1'b0; + s_axis_ready <= 1'b0; + m_axis_data <= {(NUM_OF_CHANNELS*UDATA_WIDTH){1'b0}}; + end else begin + m_axis_valid <= s_axis_valid; + s_axis_ready <= m_axis_ready; + m_axis_data <= data_out_s; + end + end + +endmodule diff --git a/src/adi/hdl/library/common/util_delay.v b/src/adi/hdl/library/common/util_delay.v new file mode 100644 index 00000000..c7a298a0 --- /dev/null +++ b/src/adi/hdl/library/common/util_delay.v @@ -0,0 +1,74 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module util_delay #( + + parameter DATA_WIDTH = 1, + // the minimum valid value for DELAY_CYCLES is 1 + parameter DELAY_CYCLES = 1) ( + + input clk, + input reset, + input din, + output [DATA_WIDTH-1:0] dout); + + reg [DATA_WIDTH-1:0] dbuf[0:(DELAY_CYCLES-1)]; + + always @(posedge clk) begin + if (reset) begin + dbuf[0] <= 0; + end else begin + dbuf[0] <= din; + end + end + + generate + genvar i; + for (i = 1; i < DELAY_CYCLES; i=i+1) begin:register_pipe + always @(posedge clk) begin + if (reset) begin + dbuf[i] <= 0; + end else begin + dbuf[i] <= dbuf[i-1]; + end + end + end + endgenerate + + assign dout = dbuf[(DELAY_CYCLES-1)]; + +endmodule diff --git a/src/adi/hdl/library/common/util_pulse_gen.v b/src/adi/hdl/library/common/util_pulse_gen.v new file mode 100644 index 00000000..93817e1b --- /dev/null +++ b/src/adi/hdl/library/common/util_pulse_gen.v @@ -0,0 +1,93 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +`timescale 1ns/1ps + +module util_pulse_gen #( + + parameter PULSE_WIDTH = 7, + parameter PULSE_PERIOD = 100000000)( // t_period * clk_freq + + input clk, + input rstn, + + input [31:0] pulse_period, + input pulse_period_en, + + output reg pulse +); + + // internal registers + + reg [(PULSE_WIDTH-1):0] pulse_width_cnt = {PULSE_WIDTH{1'b1}}; + reg [31:0] pulse_period_cnt = 32'h0; + reg [31:0] pulse_period_d = 32'b0; + + wire end_of_period_s; + + // flop the desired period + + always @(posedge clk) begin + pulse_period_d <= (pulse_period_en) ? pulse_period : PULSE_PERIOD; + end + + // a free running pulse generator + + always @(posedge clk) begin + if (rstn == 1'b0) begin + pulse_period_cnt <= 32'h0; + end else begin + pulse_period_cnt <= (pulse_period_cnt == pulse_period_d) ? 32'b0 : (pulse_period_cnt + 1); + end + end + + assign end_of_period_s = (pulse_period_cnt == pulse_period_d) ? 1'b1 : 1'b0; + + // generate pulse with a specified width + + always @(posedge clk) begin + if (rstn == 1'b0) begin + pulse_width_cnt <= 0; + pulse <= 0; + end else begin + pulse_width_cnt <= (pulse == 1'b1) ? pulse_width_cnt + 1 : {PULSE_WIDTH{1'h0}}; + if(end_of_period_s == 1'b1) begin + pulse <= 1'b1; + end else if(pulse_width_cnt == {PULSE_WIDTH{1'b1}}) begin + pulse <= 1'b0; + end + end + end + +endmodule diff --git a/src/adi/hdl/library/scripts/adi_env.tcl b/src/adi/hdl/library/scripts/adi_env.tcl new file mode 100644 index 00000000..361e8858 --- /dev/null +++ b/src/adi/hdl/library/scripts/adi_env.tcl @@ -0,0 +1,15 @@ + +# environment related stuff + +set ad_hdl_dir [file normalize [file join [file dirname [info script]] "../.."]] +set ad_phdl_dir $ad_hdl_dir + + +if [info exists ::env(ADI_HDL_DIR)] { + set ad_hdl_dir [file normalize $::env(ADI_HDL_DIR)] +} + +if [info exists ::env(ADI_PHDL_DIR)] { + set ad_phdl_dir [file normalize $::env(ADI_PHDL_DIR)] +} + diff --git a/src/adi/hdl/library/scripts/adi_ip.tcl b/src/adi/hdl/library/scripts/adi_ip.tcl new file mode 100644 index 00000000..df83cc57 --- /dev/null +++ b/src/adi/hdl/library/scripts/adi_ip.tcl @@ -0,0 +1,368 @@ +## ############################################################################################### +## ############################################################################################### +## check tool version + +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2018.2" +} + +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +## ############################################################################################### +## ############################################################################################### +## ip related stuff + +proc adi_ip_ttcl {ip_name ip_constr_files} { + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *synthesis*}] + set f [ipx::add_file $ip_constr_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_constr_files $proj_filegroup +} + +# add ttcl file to the simulation file set +proc adi_ip_sim_ttcl {ip_name ip_files} { + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *simulation*}] + set f [ipx::add_file $ip_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_files $proj_filegroup +} + +proc adi_ip_bd {ip_name ip_bd_files} { + set proj_filegroup [ipx::get_file_groups xilinx_blockdiagram -of_objects [ipx::current_core]] + if {$proj_filegroup == {}} { + set proj_filegroup [ipx::add_file_group -type xilinx_blockdiagram "" [ipx::current_core]] + } + set f [ipx::add_file $ip_bd_files $proj_filegroup] + set_property -dict [list \ + type tclSource \ + ] $f +} + +proc adi_ip_infer_streaming_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:axis_rtl:1.0 [ipx::current_core] + +} + +proc adi_ip_infer_mm_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + +} + +proc adi_set_ports_dependency {port_prefix dependency {driver_value {}}} { + foreach port [ipx::get_ports [format "%s%s" $port_prefix "*"]] { + set_property ENABLEMENT_DEPENDENCY $dependency $port + if {$driver_value != {}} { + set_property DRIVER_VALUE $driver_value $port + } + } +} + +proc adi_set_bus_dependency {bus prefix dependency} { + set_property ENABLEMENT_DEPENDENCY $dependency [ipx::get_bus_interfaces $bus -of_objects [ipx::current_core]] + adi_set_ports_dependency $prefix $dependency 0 +} + +proc adi_add_port_map {bus phys logic} { + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map +} + +proc adi_add_bus {bus_name mode abs_type bus_type port_maps} { + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + foreach port_map $port_maps { + adi_add_port_map $bus {*}$port_map + } +} + +proc adi_add_multi_bus {num bus_name_prefix mode abs_type bus_type port_maps dependency} { + for {set i 0} {$i < 8} {incr i} { + set bus_name [format "%s%d" $bus_name_prefix $i] + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + if {$dependency ne ""} { + set bus_dependency [string map [list "{i}" $i] $dependency] + set_property ENABLEMENT_DEPENDENCY $bus_dependency $bus + } + + foreach port_map $port_maps { + lassign $port_map phys logic width + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map + set_property "PHYSICAL_RIGHT" [expr $i*$width] $map + set_property "PHYSICAL_LEFT" [expr ($i+1)*$width-1] $map + } + } +} + +proc adi_add_bus_clock {clock_signal_name bus_inf_name {reset_signal_name ""} {reset_signal_mode "slave"}} { + set bus_inf_name_clean [string map {":" "_"} $bus_inf_name] + set clock_inf_name [format "%s%s" $bus_inf_name_clean "_signal_clock"] + set clock_inf [ipx::add_bus_interface $clock_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:clock_rtl:1.0" $clock_inf + set_property bus_type_vlnv "xilinx.com:signal:clock:1.0" $clock_inf + set_property display_name $clock_inf_name $clock_inf + set clock_map [ipx::add_port_map "CLK" $clock_inf] + set_property physical_name $clock_signal_name $clock_map + + set assoc_busif [ipx::add_bus_parameter "ASSOCIATED_BUSIF" $clock_inf] + set_property value $bus_inf_name $assoc_busif + + if { $reset_signal_name != "" } { + set assoc_reset [ipx::add_bus_parameter "ASSOCIATED_RESET" $clock_inf] + set_property value $reset_signal_name $assoc_reset + + set reset_inf_name [format "%s%s" $bus_inf_name_clean "_signal_reset"] + set reset_inf [ipx::add_bus_interface $reset_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:reset_rtl:1.0" $reset_inf + set_property bus_type_vlnv "xilinx.com:signal:reset:1.0" $reset_inf + set_property display_name $reset_inf_name $reset_inf + set_property interface_mode $reset_signal_mode $reset_inf + set reset_map [ipx::add_port_map "RST" $reset_inf] + set_property physical_name $reset_signal_name $reset_map + + set reset_polarity [ipx::add_bus_parameter "POLARITY" $reset_inf] + if {[string match {*[Nn]} $reset_signal_name] == 1} { + set_property value "ACTIVE_LOW" $reset_polarity + } else { + set_property value "ACTIVE_HIGH" $reset_polarity + } + } +} + +proc adi_ip_add_core_dependencies {vlnvs} { + foreach file_group [ipx::get_file_groups * -of_objects [ipx::current_core]] { + foreach vlnv $vlnvs { + ipx::add_subcore $vlnv $file_group + } + } +} + +## ############################################################################################### +## ############################################################################################### +## ip related stuff + +variable ip_constr_files + +proc adi_ip_create {ip_name} { + + global ad_hdl_dir + global ad_phdl_dir + global ip_constr_files + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + create_project $ip_name . -force + + ## Load custom message severity definitions + source $ad_hdl_dir/projects/scripts/adi_xilinx_msg.tcl + + set ip_constr_files "" + set lib_dirs $ad_hdl_dir/library + if {$ad_hdl_dir ne $ad_phdl_dir} { + lappend lib_dirs $ad_phdl_dir/library + } + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog +} + +proc adi_ip_files {ip_name ip_files} { + + global ip_constr_files + + set ip_constr_files "" + foreach m_file $ip_files { + if {[file extension $m_file] eq ".xdc"} { + lappend ip_constr_files $m_file + } + } + + set proj_fileset [get_filesets sources_1] + add_files -norecurse -scan_for_includes -fileset $proj_fileset $ip_files + set_property "top" "$ip_name" $proj_fileset +} + +proc adi_ip_properties_lite {ip_name} { + + global ip_constr_files + + ipx::package_project -root_dir . -vendor analog.com -library user -taxonomy /Analog_Devices + set_property name $ip_name [ipx::current_core] + set_property vendor_display_name {Analog Devices} [ipx::current_core] + set_property company_url {http://www.analog.com} [ipx::current_core] + + set i_families "" + foreach i_part [get_parts] { + lappend i_families [get_property FAMILY $i_part] + } + set i_families [lsort -unique $i_families] + set s_families [get_property supported_families [ipx::current_core]] + foreach i_family $i_families { + set s_families "$s_families $i_family Production" + set s_families "$s_families $i_family Beta" + } + set_property supported_families $s_families [ipx::current_core] + ipx::save_core + + ipx::remove_all_bus_interface [ipx::current_core] + set memory_maps [ipx::get_memory_maps * -of_objects [ipx::current_core]] + foreach map $memory_maps { + ipx::remove_memory_map [lindex $map 2] [ipx::current_core ] + } + ipx::save_core + + set i_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *synthesis*}] + foreach i_file $ip_constr_files { + set i_module [file tail $i_file] + regsub {_constr\.xdc} $i_module {} i_module + ipx::add_file $i_file $i_filegroup + ipx::reorder_files -front $i_file $i_filegroup + set_property SCOPED_TO_REF $i_module [ipx::get_files $i_file -of_objects $i_filegroup] + } + ipx::save_core +} + +proc adi_ip_properties {ip_name} { + + adi_ip_properties_lite $ip_name + + ipx::infer_bus_interface {\ + s_axi_awvalid \ + s_axi_awaddr \ + s_axi_awprot \ + s_axi_awready \ + s_axi_wvalid \ + s_axi_wdata \ + s_axi_wstrb \ + s_axi_wready \ + s_axi_bvalid \ + s_axi_bresp \ + s_axi_bready \ + s_axi_arvalid \ + s_axi_araddr \ + s_axi_arprot \ + s_axi_arready \ + s_axi_rvalid \ + s_axi_rdata \ + s_axi_rresp \ + s_axi_rready} \ + xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + + ipx::infer_bus_interface s_axi_aclk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] + ipx::infer_bus_interface s_axi_aresetn xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] + + set raddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_araddr -of_objects [ipx::current_core]]] + 1] + set waddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_awaddr -of_objects [ipx::current_core]]] + 1] + + if {$raddr_width != $waddr_width} { + puts [format "WARNING: AXI address width mismatch for %s (r=%d, w=%d)" $ip_name $raddr_width, $waddr_width] + set range 65536 + } else { + if {$raddr_width >= 16} { + set range 65536 + } else { + set range [expr 1 << $raddr_width] + } + } + + ipx::add_memory_map {s_axi} [ipx::current_core] + set_property slave_memory_map_ref {s_axi} [ipx::get_bus_interfaces s_axi -of_objects [ipx::current_core]] + ipx::add_address_block {axi_lite} [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]] + set_property range $range [ipx::get_address_blocks axi_lite \ + -of_objects [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]]] + ipx::associate_bus_interfaces -clock s_axi_aclk -reset s_axi_aresetn [ipx::current_core] + ipx::save_core +} + +## ############################################################################################### +## ############################################################################################### +## interface related stuff + +proc adi_if_define {name} { + + ipx::create_abstraction_definition analog.com interface ${name}_rtl 1.0 + ipx::create_bus_definition analog.com interface $name 1.0 + + set_property xml_file_name ${name}_rtl.xml [ipx::current_busabs] + set_property xml_file_name ${name}.xml [ipx::current_busdef] + set_property bus_type_vlnv analog.com:interface:${name}:1.0 [ipx::current_busabs] + + ipx::save_abstraction_definition [ipx::current_busabs] + ipx::save_bus_definition [ipx::current_busdef] +} + +proc adi_if_ports {dir width name {type none}} { + + ipx::add_bus_abstraction_port $name [ipx::current_busabs] + set m_intf [ipx::get_bus_abstraction_ports $name -of_objects [ipx::current_busabs]] + set_property master_presence required $m_intf + set_property slave_presence required $m_intf + set_property master_width $width $m_intf + set_property slave_width $width $m_intf + + set m_dir "in" + set s_dir "out" + if {$dir eq "output"} { + set m_dir "out" + set s_dir "in" + } + + set_property master_direction $m_dir $m_intf + set_property slave_direction $s_dir $m_intf + + if {$type ne "none"} { + set_property is_${type} true $m_intf + } + + ipx::save_bus_definition [ipx::current_busdef] + ipx::save_abstraction_definition [ipx::current_busabs] +} + +proc adi_if_infer_bus {if_name mode name maps} { + + ipx::add_bus_interface $name [ipx::current_core] + set m_bus_if [ipx::get_bus_interfaces $name -of_objects [ipx::current_core]] + set_property abstraction_type_vlnv ${if_name}_rtl:1.0 $m_bus_if + set_property bus_type_vlnv ${if_name}:1.0 $m_bus_if + set_property interface_mode $mode $m_bus_if + + foreach map $maps { + set m_maps [regexp -all -inline {\S+} $map] + lassign $m_maps p_name p_map + ipx::add_port_map $p_name $m_bus_if + set_property physical_name $p_map [ipx::get_port_maps $p_name -of_objects $m_bus_if] + } +} + +## ############################################################################################### +## ############################################################################################### diff --git a/src/adi/hdl/library/scripts/adi_ip_alt.tcl b/src/adi/hdl/library/scripts/adi_ip_alt.tcl new file mode 100644 index 00000000..ffd08d3e --- /dev/null +++ b/src/adi/hdl/library/scripts/adi_ip_alt.tcl @@ -0,0 +1,249 @@ +################################################################################################### +################################################################################################### +# keep interface-mess out of the way - keeping it pretty is a waste of time + +proc ad_alt_intf {type name dir width {arg_1 ""} {arg_2 ""}} { + + if {([string equal -nocase ${type} "clock"]) && ([string equal -nocase ${dir} "input"])} { + add_interface if_${name} clock sink + add_interface_port if_${name} ${name} clk ${dir} ${width} + return + } + + if {([string equal -nocase ${type} "clock"]) && ([string equal -nocase ${dir} "output"])} { + add_interface if_${name} clock source + add_interface_port if_${name} ${name} clk ${dir} ${width} + return + } + + if {([string equal -nocase ${type} "reset"]) && ([string equal -nocase ${dir} "input"])} { + add_interface if_${name} reset sink + add_interface_port if_${name} ${name} reset ${dir} ${width} + set_interface_property if_${name} associatedclock ${arg_1} + return + } + + if {([string equal -nocase ${type} "reset"]) && ([string equal -nocase ${dir} "output"])} { + add_interface if_${name} reset source + add_interface_port if_${name} ${name} reset ${dir} ${width} + set_interface_property if_${name} associatedclock ${arg_1} + set_interface_property if_${name} associatedResetSinks ${arg_2} + return + } + + if {([string equal -nocase ${type} "reset-n"]) && ([string equal -nocase ${dir} "input"])} { + add_interface if_${name} reset sink + add_interface_port if_${name} ${name} reset_n ${dir} ${width} + set_interface_property if_${name} associatedclock ${arg_1} + return + } + + if {([string equal -nocase ${type} "reset-n"]) && ([string equal -nocase ${dir} "output"])} { + add_interface if_${name} reset source + add_interface_port if_${name} ${name} reset_n ${dir} ${width} + set_interface_property if_${name} associatedclock ${arg_1} + set_interface_property if_${name} associatedResetSinks ${arg_2} + return + } + + if {([string equal -nocase ${type} "intr"]) && ([string equal -nocase ${dir} "output"])} { + add_interface if_${name} interrupt source + add_interface_port if_${name} ${name} irq ${dir} ${width} + set_interface_property if_${name} associatedclock ${arg_1} + return + } + + set remap $arg_1 + if {$arg_1 eq ""} { + set remap $name + } + + if {[string equal -nocase ${type} "signal"]} { + add_interface if_${name} conduit end + add_interface_port if_${name} ${name} ${remap} ${dir} ${width} + return + } +} + +proc ad_conduit {if_name if_port port dir width} { + + add_interface $if_name conduit end + add_interface_port $if_name $port $if_port $dir $width +} + +proc ad_generate_module_inst { inst_name mark source_file target_file } { + + set fp_source [open $source_file "r"] + set fp_target [open $target_file "w+"] + + fconfigure $fp_source -buffering line + + while { [gets $fp_source data] >= 0 } { + + # update the required module name + regsub $inst_name $data "&_$mark" data + puts $data + puts $fp_target $data + } + + close $fp_source + close $fp_target +} + +################################################################################################### +################################################################################################### + +proc ad_ip_create {pname pdisplay_name {pelabfunction ""} {pcomposefunction ""}} { + + set_module_property NAME $pname + set_module_property DISPLAY_NAME $pdisplay_name + set_module_property DESCRIPTION $pdisplay_name + set_module_property VERSION 1.0 + set_module_property GROUP "Analog Devices" + + if {$pelabfunction ne ""} { + set_module_property ELABORATION_CALLBACK $pelabfunction + } + + if {$pcomposefunction ne ""} { + set_module_property COMPOSITION_CALLBACK $pcomposefunction + } +} + +################################################################################################### +################################################################################################### + +proc ad_ip_parameter {pname ptype pdefault {phdl true} {properties {}}} { + + if {$pname eq "DEVICE_FAMILY"} { + add_parameter DEVICE_FAMILY STRING + set_parameter_property DEVICE_FAMILY SYSTEM_INFO {DEVICE_FAMILY} + set_parameter_property DEVICE_FAMILY AFFECTS_GENERATION true + set_parameter_property DEVICE_FAMILY HDL_PARAMETER false + set_parameter_property DEVICE_FAMILY ENABLED true + } else { + add_parameter $pname $ptype $pdefault + set_parameter_property $pname HDL_PARAMETER $phdl + set_parameter_property $pname ENABLED true + } + + foreach {key value} $properties { + set_parameter_property $pname $key $value + } +} + +################################################################################################### +################################################################################################### + +proc ad_ip_addfile {pname pfile} { + + set pmodule [file tail $pfile] + + regsub {\..$} $pmodule {} mname + if {$pname eq $mname} { + add_fileset_file $pmodule VERILOG PATH $pfile TOP_LEVEL_FILE + return + } + + set ptype [file extension $pfile] + if {$ptype eq ".v"} { + add_fileset_file $pmodule VERILOG PATH $pfile + return + } + if {$ptype eq ".vh"} { + add_fileset_file $pmodule VERILOG_INCLUDE PATH $pfile + return + } + if {$ptype eq ".sdc"} { + add_fileset_file $pmodule SDC PATH $pfile + return + } + if {$ptype eq ".tcl"} { + add_fileset_file $pmodule OTHER PATH $pfile + return + } +} + +proc ad_ip_files {pname pfiles {pfunction ""}} { + + add_fileset quartus_synth QUARTUS_SYNTH $pfunction "" + set_fileset_property quartus_synth TOP_LEVEL $pname + foreach pfile $pfiles { + ad_ip_addfile $pname $pfile + } + + add_fileset quartus_sim SIM_VERILOG $pfunction "" + set_fileset_property quartus_sim TOP_LEVEL $pname + foreach pfile $pfiles { + ad_ip_addfile $pname $pfile + } +} + +################################################################################################### +################################################################################################### + +proc ad_ip_intf_s_axi {aclk arstn {addr_width 16}} { + + add_interface s_axi_clock clock end + add_interface_port s_axi_clock ${aclk} clk Input 1 + + add_interface s_axi_reset reset end + set_interface_property s_axi_reset associatedClock s_axi_clock + add_interface_port s_axi_reset ${arstn} reset_n Input 1 + + add_interface s_axi axi4lite end + set_interface_property s_axi associatedClock s_axi_clock + set_interface_property s_axi associatedReset s_axi_reset + add_interface_port s_axi s_axi_awvalid awvalid Input 1 + add_interface_port s_axi s_axi_awaddr awaddr Input $addr_width + add_interface_port s_axi s_axi_awprot awprot Input 3 + add_interface_port s_axi s_axi_awready awready Output 1 + add_interface_port s_axi s_axi_wvalid wvalid Input 1 + add_interface_port s_axi s_axi_wdata wdata Input 32 + add_interface_port s_axi s_axi_wstrb wstrb Input 4 + add_interface_port s_axi s_axi_wready wready Output 1 + add_interface_port s_axi s_axi_bvalid bvalid Output 1 + add_interface_port s_axi s_axi_bresp bresp Output 2 + add_interface_port s_axi s_axi_bready bready Input 1 + add_interface_port s_axi s_axi_arvalid arvalid Input 1 + add_interface_port s_axi s_axi_araddr araddr Input $addr_width + add_interface_port s_axi s_axi_arprot arprot Input 3 + add_interface_port s_axi s_axi_arready arready Output 1 + add_interface_port s_axi s_axi_rvalid rvalid Output 1 + add_interface_port s_axi s_axi_rresp rresp Output 2 + add_interface_port s_axi s_axi_rdata rdata Output 32 + add_interface_port s_axi s_axi_rready rready Input 1 +} + +################################################################################################### +################################################################################################### + +proc ad_ip_modfile {ifile ofile flist} { + + global ad_hdl_dir + + set srcfile [open ${ad_hdl_dir}/library/altera/common/${ifile} r] + set dstfile [open ${ofile} w] + + regsub {\..$} $ifile {} imodule + regsub {\..$} $ofile {} omodule + + while {[gets $srcfile srcline] >= 0} { + regsub __${imodule}__ $srcline $omodule dstline + set index 0 + foreach fword $flist { + incr index + regsub __${imodule}_${index}__ $dstline $fword dstline + } + puts $dstfile $dstline + } + + close $srcfile + close $dstfile + + ad_ip_addfile ad_ip_addfile $ofile +} + +################################################################################################### +################################################################################################### + diff --git a/src/adi/hdl/library/scripts/library.mk b/src/adi/hdl/library/scripts/library.mk new file mode 100644 index 00000000..e0a4b270 --- /dev/null +++ b/src/adi/hdl/library/scripts/library.mk @@ -0,0 +1,78 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +#################################################################################### + +# Assumes this file is in library/scripts/library.mk +HDL_LIBRARY_PATH := $(subst scripts/library.mk,,$(lastword $(MAKEFILE_LIST))) + +include $(HDL_LIBRARY_PATH)../quiet.mk + +VIVADO := vivado -mode batch -source + +CLEAN_TARGET := *.cache +CLEAN_TARGET += *.data +CLEAN_TARGET += *.xpr +CLEAN_TARGET += *.log +CLEAN_TARGET += component.xml +CLEAN_TARGET += *.jou +CLEAN_TARGET += xgui +CLEAN_TARGET += *.ip_user_files +CLEAN_TARGET += *.srcs +CLEAN_TARGET += *.hw +CLEAN_TARGET += *.sim +CLEAN_TARGET += .Xil +CLEAN_TARGET += .timestamp_altera + +GENERIC_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_env.tcl + +.PHONY: all altera altera_dep xilinx xilinx_dep clean clean-all + +all: altera xilinx + +clean: clean-all + +clean-all: + $(call clean, \ + $(CLEAN_TARGET), \ + $(HL)$(LIBRARY_NAME)$(NC) library) + +ifneq ($(ALTERA_DEPS),) + +ALTERA_DEPS += $(GENERIC_DEPS) +ALTERA_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip_alt.tcl +ALTERA_DEPS += $(foreach dep,$(ALTERA_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_altera) + +altera: altera_dep .timestamp_altera + +.timestamp_altera: $(ALTERA_DEPS) + touch $@ + +altera_dep: + @for lib in $(ALTERA_LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} altera || exit $$?; \ + done +endif + +ifneq ($(XILINX_DEPS),) + +XILINX_DEPS += $(GENERIC_DEPS) +XILINX_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip.tcl +XILINX_DEPS += $(foreach dep,$(XILINX_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/component.xml) + +xilinx: xilinx_dep component.xml + +component.xml: $(XILINX_DEPS) + -rm -rf $(CLEAN_TARGET) + $(call build, \ + $(VIVADO) $(LIBRARY_NAME)_ip.tcl, \ + $(LIBRARY_NAME)_ip.log, \ + $(HL)$(LIBRARY_NAME)$(NC) library) + +xilinx_dep: + @for lib in $(XILINX_LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} xilinx || exit $$?; \ + done + @for intf in $(XILINX_INTERFACE_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${intf} xilinx || exit $$?; \ + done +endif diff --git a/src/adi/hdl/library/xilinx/common/ad_data_clk.v b/src/adi/hdl/library/xilinx/common/ad_data_clk.v new file mode 100644 index 00000000..42027091 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_data_clk.v @@ -0,0 +1,84 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_data_clk #( + + parameter SINGLE_ENDED = 0, + parameter DEVICE_TYPE = 0) ( + + input rst, + output locked, + + input clk_in_p, + input clk_in_n, + output clk); + + localparam VIRTEX7 = 0; + localparam ULTRASCALE_PLUS = 2; + localparam ULTRASCALE = 3; + + // internal signals + + wire clk_ibuf_s; + + // defaults + + assign locked = 1'b1; + + // instantiations + + generate + if (SINGLE_ENDED == 1) begin + IBUFG i_rx_clk_ibuf ( + .I (clk_in_p), + .O (clk_ibuf_s)); + end else begin + IBUFGDS i_rx_clk_ibuf ( + .I (clk_in_p), + .IB (clk_in_n), + .O (clk_ibuf_s)); + end + endgenerate + + BUFG i_clk_gbuf ( + .I (clk_ibuf_s), + .O (clk)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_data_in.v b/src/adi/hdl/library/xilinx/common/ad_data_in.v new file mode 100644 index 00000000..a07af266 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_data_in.v @@ -0,0 +1,214 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_data_in #( + + // parameters + + parameter SINGLE_ENDED = 0, + parameter DEVICE_TYPE = 0, + parameter IODELAY_ENABLE = 1, + parameter IODELAY_CTRL = 0, + parameter IODELAY_GROUP = "dev_if_delay_group") ( + + // data interface + + input rx_clk, + input rx_data_in_p, + input rx_data_in_n, + output rx_data_p, + output rx_data_n, + + // delay-data interface + + input up_clk, + input up_dld, + input [ 4:0] up_dwdata, + output [ 4:0] up_drdata, + + // delay-cntrl interface + + input delay_clk, + input delay_rst, + output delay_locked); + + // internal parameters + + localparam NONE = -1; + localparam VIRTEX7 = 0; + localparam ULTRASCALE_PLUS = 2; + localparam ULTRASCALE = 3; + + localparam IODELAY_CTRL_ENABLED = (IODELAY_ENABLE == 1) ? IODELAY_CTRL : 0; + localparam IODELAY_CTRL_SIM_DEVICE = (DEVICE_TYPE == ULTRASCALE_PLUS) ? "ULTRASCALE" : + (DEVICE_TYPE == ULTRASCALE) ? "ULTRASCALE" : "7SERIES"; + + localparam IODELAY_DEVICE_TYPE = (IODELAY_ENABLE == 1) ? DEVICE_TYPE : NONE; + localparam IODELAY_SIM_DEVICE = (DEVICE_TYPE == ULTRASCALE_PLUS) ? "ULTRASCALE_PLUS" : + (DEVICE_TYPE == ULTRASCALE) ? "ULTRASCALE" : "7SERIES"; + + // internal signals + + wire rx_data_ibuf_s; + wire rx_data_idelay_s; + wire [ 8:0] up_drdata_s; + + // delay controller + + generate + if (IODELAY_CTRL_ENABLED == 0) begin + assign delay_locked = 1'b1; + end else begin + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYCTRL #(.SIM_DEVICE (IODELAY_CTRL_SIM_DEVICE)) i_delay_ctrl ( + .RST (delay_rst), + .REFCLK (delay_clk), + .RDY (delay_locked)); + end + endgenerate + + // receive data interface, ibuf -> idelay -> iddr + + generate + if (SINGLE_ENDED == 1) begin + IBUF i_rx_data_ibuf ( + .I (rx_data_in_p), + .O (rx_data_ibuf_s)); + end else begin + IBUFDS i_rx_data_ibuf ( + .I (rx_data_in_p), + .IB (rx_data_in_n), + .O (rx_data_ibuf_s)); + end + endgenerate + + // idelay + + generate + if (IODELAY_DEVICE_TYPE == VIRTEX7) begin + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYE2 #( + .CINVCTRL_SEL ("FALSE"), + .DELAY_SRC ("IDATAIN"), + .HIGH_PERFORMANCE_MODE ("FALSE"), + .IDELAY_TYPE ("VAR_LOAD"), + .IDELAY_VALUE (0), + .REFCLK_FREQUENCY (200.0), + .PIPE_SEL ("FALSE"), + .SIGNAL_PATTERN ("DATA")) + i_rx_data_idelay ( + .CE (1'b0), + .INC (1'b0), + .DATAIN (1'b0), + .LDPIPEEN (1'b0), + .CINVCTRL (1'b0), + .REGRST (1'b0), + .C (up_clk), + .IDATAIN (rx_data_ibuf_s), + .DATAOUT (rx_data_idelay_s), + .LD (up_dld), + .CNTVALUEIN (up_dwdata), + .CNTVALUEOUT (up_drdata)); + end + endgenerate + + generate + if ((IODELAY_DEVICE_TYPE == ULTRASCALE) || (IODELAY_DEVICE_TYPE == ULTRASCALE_PLUS)) begin + assign up_drdata = up_drdata_s[8:4]; + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYE3 #( + .SIM_DEVICE (IODELAY_SIM_DEVICE), + .DELAY_SRC ("IDATAIN"), + .DELAY_TYPE ("VAR_LOAD"), + .REFCLK_FREQUENCY (200.0), + .DELAY_FORMAT ("COUNT")) + i_rx_data_idelay ( + .CASC_RETURN (1'b0), + .CASC_IN (1'b0), + .CASC_OUT (), + .CE (1'b0), + .CLK (up_clk), + .INC (1'b0), + .LOAD (up_dld), + .CNTVALUEIN ({up_dwdata, 4'd0}), + .CNTVALUEOUT (up_drdata_s), + .DATAIN (1'b0), + .IDATAIN (rx_data_ibuf_s), + .DATAOUT (rx_data_idelay_s), + .RST (1'b0), + .EN_VTC (~up_dld)); + end + endgenerate + + generate + if (IODELAY_DEVICE_TYPE == NONE) begin + assign rx_data_idelay_s = rx_data_ibuf_s; + assign up_drdata = 5'd0; + end + endgenerate + + // iddr + + generate + if ((DEVICE_TYPE == ULTRASCALE) || (DEVICE_TYPE == ULTRASCALE_PLUS)) begin + IDDRE1 #(.DDR_CLK_EDGE ("SAME_EDGE")) i_rx_data_iddr ( + .R (1'b0), + .C (rx_clk), + .CB (~rx_clk), + .D (rx_data_idelay_s), + .Q1 (rx_data_p), + .Q2 (rx_data_n)); + end + endgenerate + + generate + if (DEVICE_TYPE == VIRTEX7) begin + IDDR #(.DDR_CLK_EDGE ("SAME_EDGE")) i_rx_data_iddr ( + .CE (1'b1), + .R (1'b0), + .S (1'b0), + .C (rx_clk), + .D (rx_data_idelay_s), + .Q1 (rx_data_p), + .Q2 (rx_data_n)); + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_data_out.v b/src/adi/hdl/library/xilinx/common/ad_data_out.v new file mode 100644 index 00000000..e292cabd --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_data_out.v @@ -0,0 +1,181 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_data_out #( + + parameter DEVICE_TYPE = 0, + parameter SINGLE_ENDED = 0, + parameter IODELAY_ENABLE = 0, + parameter IODELAY_CTRL = 0, + parameter IODELAY_GROUP = "dev_if_delay_group") ( + + // data interface + + input tx_clk, + input tx_data_p, + input tx_data_n, + output tx_data_out_p, + output tx_data_out_n, + + // delay-data interface + + input up_clk, + input up_dld, + input [ 4:0] up_dwdata, + output [ 4:0] up_drdata, + + // delay-cntrl interface + + input delay_clk, + input delay_rst, + output delay_locked); + + localparam NONE = -1; + localparam VIRTEX7 = 0; + localparam ULTRASCALE_PLUS = 2; + localparam ULTRASCALE = 3; + + localparam IODELAY_CTRL_ENABLED = (IODELAY_ENABLE == 1) ? IODELAY_CTRL : 0; + localparam IODELAY_CTRL_SIM_DEVICE = (DEVICE_TYPE == ULTRASCALE_PLUS) ? "ULTRASCALE" : + (DEVICE_TYPE == ULTRASCALE) ? "ULTRASCALE" : "7SERIES"; + + localparam IODELAY_DEVICE_TYPE = (IODELAY_ENABLE == 1) ? DEVICE_TYPE : NONE; + localparam IODELAY_SIM_DEVICE = (DEVICE_TYPE == ULTRASCALE_PLUS) ? "ULTRASCALE_PLUS_ES1" : + (DEVICE_TYPE == ULTRASCALE) ? "ULTRASCALE" : "7SERIES"; + + // internal signals + + wire tx_data_oddr_s; + wire tx_data_odelay_s; + + // delay controller + + generate + if (IODELAY_CTRL_ENABLED == 0) begin + assign delay_locked = 1'b1; + end else begin + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYCTRL #(.SIM_DEVICE (IODELAY_CTRL_SIM_DEVICE)) i_delay_ctrl ( + .RST (delay_rst), + .REFCLK (delay_clk), + .RDY (delay_locked)); + end + endgenerate + + // transmit data interface, oddr -> odelay -> obuf + + generate + if ((DEVICE_TYPE == ULTRASCALE) || (DEVICE_TYPE == ULTRASCALE_PLUS)) begin + ODDRE1 i_tx_data_oddr ( + .SR (1'b0), + .C (tx_clk), + .D1 (tx_data_n), + .D2 (tx_data_p), + .Q (tx_data_oddr_s)); + end + endgenerate + + generate + if (DEVICE_TYPE == VIRTEX7) begin + ODDR #(.DDR_CLK_EDGE ("SAME_EDGE")) i_tx_data_oddr ( + .CE (1'b1), + .R (1'b0), + .S (1'b0), + .C (tx_clk), + .D1 (tx_data_n), + .D2 (tx_data_p), + .Q (tx_data_oddr_s)); + end + endgenerate + + // odelay + + generate + if (IODELAY_DEVICE_TYPE == VIRTEX7) begin + (* IODELAY_GROUP = IODELAY_GROUP *) + ODELAYE2 #( + .CINVCTRL_SEL ("FALSE"), + .DELAY_SRC ("ODATAIN"), + .HIGH_PERFORMANCE_MODE ("FALSE"), + .ODELAY_TYPE ("VAR_LOAD"), + .ODELAY_VALUE (0), + .REFCLK_FREQUENCY (200.0), + .PIPE_SEL ("FALSE"), + .SIGNAL_PATTERN ("DATA")) + i_tx_data_odelay ( + .CE (1'b0), + .CLKIN (1'b0), + .INC (1'b0), + .LDPIPEEN (1'b0), + .CINVCTRL (1'b0), + .REGRST (1'b0), + .C (up_clk), + .ODATAIN (tx_data_oddr_s), + .DATAOUT (tx_data_odelay_s), + .LD (up_dld), + .CNTVALUEIN (up_dwdata), + .CNTVALUEOUT (up_drdata)); + end + endgenerate + + generate + if (IODELAY_DEVICE_TYPE == NONE) begin + assign up_drdata = 5'd0; + assign tx_data_odelay_s = tx_data_oddr_s; + end + endgenerate + + // obuf + + generate + if (SINGLE_ENDED == 1) begin + assign tx_data_out_n = 1'b0; + OBUF i_tx_data_obuf ( + .I (tx_data_odelay_s), + .O (tx_data_out_p)); + end else begin + OBUFDS i_tx_data_obuf ( + .I (tx_data_odelay_s), + .O (tx_data_out_p), + .OB (tx_data_out_n)); + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_dcfilter.v b/src/adi/hdl/library/xilinx/common/ad_dcfilter.v new file mode 100644 index 00000000..47a2db00 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_dcfilter.v @@ -0,0 +1,197 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// dc filter- y(n) = c*x(n) + (1-c)*y(n-1) + +`timescale 1ps/1ps + +module ad_dcfilter #( + + // data path disable + + parameter DISABLE = 0) ( + + // data interface + + input clk, + input valid, + input [15:0] data, + output valid_out, + output [15:0] data_out, + + // control interface + + input dcfilt_enb, + input [15:0] dcfilt_coeff, + input [15:0] dcfilt_offset); + + // internal registers + + reg [15:0] dcfilt_coeff_d = 'd0; + reg [47:0] dc_offset = 'd0; + reg [47:0] dc_offset_d = 'd0; + reg valid_d = 'd0; + reg [15:0] data_d = 'd0; + reg valid_2d = 'd0; + reg [15:0] data_2d = 'd0; + reg [15:0] data_dcfilt = 'd0; + reg valid_int = 'd0; + reg [15:0] data_int = 'd0; + + // internal signals + + wire [47:0] dc_offset_s; + + // data-path disable + + generate + if (DISABLE == 1) begin + assign valid_out = valid; + assign data_out = data; + end else begin + assign valid_out = valid_int; + assign data_out = data_int; + end + endgenerate + + // dcfilt_coeff is flopped so to remove warnings from vivado + + always @(posedge clk) begin + dcfilt_coeff_d <= dcfilt_coeff; + end + + // removing dc offset + + always @(posedge clk) begin + dc_offset <= dc_offset_s; + dc_offset_d <= dc_offset; + valid_d <= valid; + if (valid == 1'b1) begin + data_d <= data + dcfilt_offset; + end + valid_2d <= valid_d; + data_2d <= data_d; + data_dcfilt <= data_d - dc_offset[32:17]; + if (dcfilt_enb == 1'b1) begin + valid_int <= valid_2d; + data_int <= data_dcfilt; + end else begin + valid_int <= valid_2d; + data_int <= data_2d; + end + end + + // dsp slice instance ((D-A)*B)+C + + DSP48E1 #( + .ACASCREG (1), + .ADREG (1), + .ALUMODEREG (0), + .AREG (1), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (1), + .BREG (1), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (1), + .DREG (0), + .INMODEREG (0), + .MASK (48'h3fffffffffff), + .MREG (1), + .OPMODEREG (0), + .PATTERN (48'h000000000000), + .PREG (1), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("MULTIPLY"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48")) + i_dsp48e1 ( + .CLK (clk), + .A ({{14{dc_offset_s[32]}}, dc_offset_s[32:17]}), + .B ({{2{dcfilt_coeff_d[15]}}, dcfilt_coeff_d}), + .C (dc_offset_d), + .D ({{9{data_d[15]}}, data_d}), + .MULTSIGNIN (1'd0), + .CARRYIN (1'd0), + .CARRYCASCIN (1'd0), + .ACIN (30'd0), + .BCIN (18'd0), + .PCIN (48'd0), + .P (dc_offset_s), + .MULTSIGNOUT (), + .CARRYOUT (), + .CARRYCASCOUT (), + .ACOUT (), + .BCOUT (), + .PCOUT (), + .ALUMODE (4'd0), + .CARRYINSEL (3'd0), + .INMODE (5'b01100), + .OPMODE (7'b0110101), + .PATTERNBDETECT (), + .PATTERNDETECT (), + .OVERFLOW (), + .UNDERFLOW (), + .CEA1 (1'd0), + .CEA2 (1'd1), + .CEAD (1'd1), + .CEALUMODE (1'd0), + .CEB1 (1'd0), + .CEB2 (1'd1), + .CEC (1'd1), + .CECARRYIN (1'd0), + .CECTRL (1'd0), + .CED (1'd1), + .CEINMODE (1'd0), + .CEM (1'd1), + .CEP (1'd0), + .RSTA (1'd0), + .RSTALLCARRYIN (1'd0), + .RSTALUMODE (1'd0), + .RSTB (1'd0), + .RSTC (1'd0), + .RSTCTRL (1'd0), + .RSTD (1'd0), + .RSTINMODE (1'd0), + .RSTM (1'd0), + .RSTP (1'd0)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_iobuf.v b/src/adi/hdl/library/xilinx/common/ad_iobuf.v new file mode 100644 index 00000000..7711fa1b --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_iobuf.v @@ -0,0 +1,59 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_iobuf #( + + parameter DATA_WIDTH = 1) ( + + input [(DATA_WIDTH-1):0] dio_t, + input [(DATA_WIDTH-1):0] dio_i, + output [(DATA_WIDTH-1):0] dio_o, + inout [(DATA_WIDTH-1):0] dio_p); + + + genvar n; + generate + for (n = 0; n < DATA_WIDTH; n = n + 1) begin: g_iobuf + assign dio_o[n] = dio_p[n]; + assign dio_p[n] = (dio_t[n] == 1'b1) ? 1'bz : dio_i[n]; + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_mmcm_drp.v b/src/adi/hdl/library/xilinx/common/ad_mmcm_drp.v new file mode 100644 index 00000000..0fc9a702 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_mmcm_drp.v @@ -0,0 +1,253 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// MMCM_OR_BUFR_N with DRP and device specific + +`timescale 1ns/100ps + +module ad_mmcm_drp #( + + parameter MMCM_DEVICE_TYPE = 0, + parameter MMCM_CLKIN_PERIOD = 1.667, + parameter MMCM_CLKIN2_PERIOD = 1.667, + parameter MMCM_VCO_DIV = 6, + parameter MMCM_VCO_MUL = 12.000, + parameter MMCM_CLK0_DIV = 2.000, + parameter MMCM_CLK0_PHASE = 0.000, + parameter MMCM_CLK1_DIV = 6, + parameter MMCM_CLK1_PHASE = 0.000, + parameter MMCM_CLK2_DIV = 2.000, + parameter MMCM_CLK2_PHASE = 0.000) ( + + // clocks + + input clk, + input clk2, + input clk_sel, + input mmcm_rst, + output mmcm_clk_0, + output mmcm_clk_1, + output mmcm_clk_2, + + // drp interface + + input up_clk, + input up_rstn, + input up_drp_sel, + input up_drp_wr, + input [11:0] up_drp_addr, + input [15:0] up_drp_wdata, + output reg [15:0] up_drp_rdata, + output reg up_drp_ready, + output reg up_drp_locked); + + localparam MMCM_DEVICE_7SERIES = 0; + localparam MMCM_DEVICE_ULTRASCALE = 2; + + + // internal registers + + reg up_drp_locked_m1 = 'd0; + + // internal signals + + wire bufg_fb_clk_s; + wire mmcm_fb_clk_s; + wire mmcm_clk_0_s; + wire mmcm_clk_1_s; + wire mmcm_clk_2_s; + wire mmcm_locked_s; + wire [15:0] up_drp_rdata_s; + wire up_drp_ready_s; + + // drp read and locked + + always @(posedge up_clk) begin + if (up_rstn == 1'b0) begin + up_drp_rdata <= 'd0; + up_drp_ready <= 'd0; + up_drp_locked_m1 <= 1'd0; + up_drp_locked <= 1'd0; + end else begin + up_drp_rdata <= up_drp_rdata_s; + up_drp_ready <= up_drp_ready_s; + up_drp_locked_m1 <= mmcm_locked_s; + up_drp_locked <= up_drp_locked_m1; + end + end + + // instantiations + + generate + if (MMCM_DEVICE_TYPE == MMCM_DEVICE_7SERIES) begin + MMCME2_ADV #( + .BANDWIDTH ("OPTIMIZED"), + .CLKOUT4_CASCADE ("FALSE"), + .COMPENSATION ("ZHOLD"), + .STARTUP_WAIT ("FALSE"), + .DIVCLK_DIVIDE (MMCM_VCO_DIV), + .CLKFBOUT_MULT_F (MMCM_VCO_MUL), + .CLKFBOUT_PHASE (0.000), + .CLKFBOUT_USE_FINE_PS ("FALSE"), + .CLKOUT0_DIVIDE_F (MMCM_CLK0_DIV), + .CLKOUT0_PHASE (MMCM_CLK0_PHASE), + .CLKOUT0_DUTY_CYCLE (0.500), + .CLKOUT0_USE_FINE_PS ("FALSE"), + .CLKOUT1_DIVIDE (MMCM_CLK1_DIV), + .CLKOUT1_PHASE (MMCM_CLK1_PHASE), + .CLKOUT1_DUTY_CYCLE (0.500), + .CLKOUT1_USE_FINE_PS ("FALSE"), + .CLKOUT2_DIVIDE (MMCM_CLK2_DIV), + .CLKOUT2_PHASE (MMCM_CLK2_PHASE), + .CLKOUT2_DUTY_CYCLE (0.500), + .CLKOUT2_USE_FINE_PS ("FALSE"), + .CLKIN1_PERIOD (MMCM_CLKIN_PERIOD), + .CLKIN2_PERIOD (MMCM_CLKIN2_PERIOD), + .REF_JITTER1 (0.010)) + i_mmcm ( + .CLKIN1 (clk), + .CLKFBIN (bufg_fb_clk_s), + .CLKFBOUT (mmcm_fb_clk_s), + .CLKOUT0 (mmcm_clk_0_s), + .CLKOUT1 (mmcm_clk_1_s), + .CLKOUT2 (mmcm_clk_2_s), + .LOCKED (mmcm_locked_s), + .DCLK (up_clk), + .DEN (up_drp_sel), + .DADDR (up_drp_addr[6:0]), + .DWE (up_drp_wr), + .DI (up_drp_wdata), + .DO (up_drp_rdata_s), + .DRDY (up_drp_ready_s), + .CLKFBOUTB (), + .CLKOUT0B (), + .CLKOUT1B (), + .CLKOUT2B (), + .CLKOUT3 (), + .CLKOUT3B (), + .CLKOUT4 (), + .CLKOUT5 (), + .CLKOUT6 (), + .CLKIN2 (clk2), + .CLKINSEL (clk_sel), + .PSCLK (1'b0), + .PSEN (1'b0), + .PSINCDEC (1'b0), + .PSDONE (), + .CLKINSTOPPED (), + .CLKFBSTOPPED (), + .PWRDWN (1'b0), + .RST (mmcm_rst)); + + BUFG i_fb_clk_bufg (.I (mmcm_fb_clk_s), .O (bufg_fb_clk_s)); + BUFG i_clk_0_bufg (.I (mmcm_clk_0_s), .O (mmcm_clk_0)); + BUFG i_clk_1_bufg (.I (mmcm_clk_1_s), .O (mmcm_clk_1)); + BUFG i_clk_2_bufg (.I (mmcm_clk_2_s), .O (mmcm_clk_2)); + + end else if (MMCM_DEVICE_TYPE == MMCM_DEVICE_ULTRASCALE) begin + MMCME3_ADV #( + .BANDWIDTH ("OPTIMIZED"), + .CLKOUT4_CASCADE ("FALSE"), + .COMPENSATION ("AUTO"), + .STARTUP_WAIT ("FALSE"), + + .DIVCLK_DIVIDE (MMCM_VCO_DIV), + .CLKFBOUT_MULT_F (MMCM_VCO_MUL), + .CLKFBOUT_PHASE (0.000), + .CLKFBOUT_USE_FINE_PS ("FALSE"), + .CLKOUT0_DIVIDE_F (MMCM_CLK0_DIV), + .CLKOUT0_PHASE (MMCM_CLK0_PHASE), + .CLKOUT0_DUTY_CYCLE (0.500), + .CLKOUT0_USE_FINE_PS ("FALSE"), + .CLKOUT1_DIVIDE (MMCM_CLK1_DIV), + .CLKOUT1_PHASE (MMCM_CLK1_PHASE), + .CLKOUT1_DUTY_CYCLE (0.500), + .CLKOUT1_USE_FINE_PS ("FALSE"), + .CLKOUT2_DIVIDE (MMCM_CLK2_DIV), + .CLKOUT2_PHASE (MMCM_CLK2_PHASE), + .CLKOUT2_DUTY_CYCLE (0.500), + .CLKOUT2_USE_FINE_PS ("FALSE"), + .CLKIN1_PERIOD (MMCM_CLKIN_PERIOD), + .CLKIN2_PERIOD (MMCM_CLKIN2_PERIOD), + .REF_JITTER1 (0.010)) + i_mmcme3 ( + .CLKIN1 (clk), + .CLKFBIN (bufg_fb_clk_s), + .CLKFBOUT (mmcm_fb_clk_s), + .CLKOUT0 (mmcm_clk_0_s), + .CLKOUT1 (mmcm_clk_1_s), + .CLKOUT2 (mmcm_clk_2_s), + .LOCKED (mmcm_locked_s), + .DCLK (up_clk), + .DEN (up_drp_sel), + .DADDR (up_drp_addr[6:0]), + .DWE (up_drp_wr), + .DI (up_drp_wdata), + .DO (up_drp_rdata_s), + .DRDY (up_drp_ready_s), + .CLKFBOUTB (), + .CLKOUT0B (), + .CLKOUT1B (), + .CLKOUT2B (), + .CLKOUT3 (), + .CLKOUT3B (), + .CLKOUT4 (), + .CLKOUT5 (), + .CLKOUT6 (), + .CLKIN2 (clk2), + .CLKINSEL (clk_sel), + .PSCLK (1'b0), + .PSEN (1'b0), + .PSINCDEC (1'b0), + .PSDONE (), + .CLKINSTOPPED (), + .CLKFBSTOPPED (), + .PWRDWN (1'b0), + .CDDCREQ (1'b0), + .CDDCDONE (), + .RST (mmcm_rst)); + + BUFG i_fb_clk_bufg (.I (mmcm_fb_clk_s), .O (bufg_fb_clk_s)); + BUFG i_clk_0_bufg (.I (mmcm_clk_0_s), .O (mmcm_clk_0)); + BUFG i_clk_1_bufg (.I (mmcm_clk_1_s), .O (mmcm_clk_1)); + BUFG i_clk_2_bufg (.I (mmcm_clk_2_s), .O (mmcm_clk_2)); + + end + endgenerate + + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_mul.v b/src/adi/hdl/library/xilinx/common/ad_mul.v new file mode 100644 index 00000000..9b64ebcc --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_mul.v @@ -0,0 +1,85 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ps/1ps + +module ad_mul #( + + parameter A_DATA_WIDTH = 17, + parameter B_DATA_WIDTH = 17, + parameter DELAY_DATA_WIDTH = 16) ( + + // data_p = data_a * data_b; + + input clk, + input [ A_DATA_WIDTH-1:0] data_a, + input [ B_DATA_WIDTH-1:0] data_b, + output [A_DATA_WIDTH + B_DATA_WIDTH-1:0] data_p, + + // delay interface + + input [(DELAY_DATA_WIDTH-1):0] ddata_in, + output reg [(DELAY_DATA_WIDTH-1):0] ddata_out); + + + // internal registers + + reg [(DELAY_DATA_WIDTH-1):0] p1_ddata = 'd0; + reg [(DELAY_DATA_WIDTH-1):0] p2_ddata = 'd0; + + // a/b reg, m-reg, p-reg delay match + + always @(posedge clk) begin + p1_ddata <= ddata_in; + p2_ddata <= p1_ddata; + ddata_out <= p2_ddata; + end + + MULT_MACRO #( + .LATENCY (3), + .WIDTH_A (A_DATA_WIDTH), + .WIDTH_B (B_DATA_WIDTH)) + i_mult_macro ( + .CE (1'b1), + .RST (1'b0), + .CLK (clk), + .A (data_a), + .B (data_b), + .P (data_p)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_rst_constr.xdc b/src/adi/hdl/library/xilinx/common/ad_rst_constr.xdc new file mode 100644 index 00000000..7aab6af3 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_rst_constr.xdc @@ -0,0 +1,8 @@ + +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *rst_async_d*_reg}] +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *rst_sync_reg}] + +set_false_path -to [get_pins *rst_sync_reg/PRE] +set_false_path -to [get_pins *rst_async_d1_reg/PRE] +set_false_path -to [get_pins *rst_async_d2_reg/PRE] + diff --git a/src/adi/hdl/library/xilinx/common/ad_serdes_clk.v b/src/adi/hdl/library/xilinx/common/ad_serdes_clk.v new file mode 100644 index 00000000..53742998 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_serdes_clk.v @@ -0,0 +1,160 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// serial data output interface: serdes(x8) + +`timescale 1ps/1ps + +module ad_serdes_clk #( + + parameter DEVICE_TYPE = 0, + parameter DDR_OR_SDR_N = 1, + parameter CLKIN_DS_OR_SE_N = 1, + parameter SERDES_FACTOR = 8, + parameter MMCM_OR_BUFR_N = 1, + parameter MMCM_CLKIN_PERIOD = 1.667, + parameter MMCM_VCO_DIV = 6, + parameter MMCM_VCO_MUL = 12.000, + parameter MMCM_CLK0_DIV = 2.000, + parameter MMCM_CLK1_DIV = 6) ( + + // clock and divided clock + + input rst, + input clk_in_p, + input clk_in_n, + output clk, + output div_clk, + output out_clk, + output loaden, + output [ 7:0] phase, + + // drp interface + + input up_clk, + input up_rstn, + input up_drp_sel, + input up_drp_wr, + input [11:0] up_drp_addr, + input [31:0] up_drp_wdata, + output [31:0] up_drp_rdata, + output up_drp_ready, + output up_drp_locked); + + localparam BUFR_DIVIDE = (DDR_OR_SDR_N == 1'b1) ? SERDES_FACTOR / 2 : SERDES_FACTOR; + + // internal signals + + wire clk_in_s; + + // defaults + + assign loaden = 'd0; + assign phase = 'd0; + assign up_drp_rdata[31:16] = 'd0; + + // instantiations + + generate + if (CLKIN_DS_OR_SE_N == 1) begin + IBUFGDS i_clk_in_ibuf ( + .I (clk_in_p), + .IB (clk_in_n), + .O (clk_in_s)); + end else begin + IBUF IBUF_inst ( + .O(clk_in_s), + .I(clk_in_p)); + end + endgenerate + + generate + if (MMCM_OR_BUFR_N == 1) begin + ad_mmcm_drp #( + .MMCM_DEVICE_TYPE (DEVICE_TYPE), + .MMCM_CLKIN_PERIOD (MMCM_CLKIN_PERIOD), + .MMCM_CLKIN2_PERIOD (MMCM_CLKIN_PERIOD), + .MMCM_VCO_DIV (MMCM_VCO_DIV), + .MMCM_VCO_MUL (MMCM_VCO_MUL), + .MMCM_CLK0_DIV (MMCM_CLK0_DIV), + .MMCM_CLK0_PHASE (0.0), + .MMCM_CLK1_DIV (MMCM_CLK1_DIV), + .MMCM_CLK1_PHASE (0.0), + .MMCM_CLK2_DIV (MMCM_CLK0_DIV), + .MMCM_CLK2_PHASE (90.0)) + i_mmcm_drp ( + .clk (clk_in_s), + .clk2 (1'b0), + .clk_sel (1'b1), + .mmcm_rst (rst), + .mmcm_clk_0 (clk), + .mmcm_clk_1 (div_clk), + .mmcm_clk_2 (out_clk), + .up_clk (up_clk), + .up_rstn (up_rstn), + .up_drp_sel (up_drp_sel), + .up_drp_wr (up_drp_wr), + .up_drp_addr (up_drp_addr), + .up_drp_wdata (up_drp_wdata[15:0]), + .up_drp_rdata (up_drp_rdata[15:0]), + .up_drp_ready (up_drp_ready), + .up_drp_locked (up_drp_locked)); + end + endgenerate + + generate + if (MMCM_OR_BUFR_N == 0) begin + BUFIO i_clk_buf ( + .I (clk_in_s), + .O (clk)); + + BUFR #(.BUFR_DIVIDE(BUFR_DIVIDE)) i_div_clk_buf ( + .CLR (1'b0), + .CE (1'b1), + .I (clk_in_s), + .O (div_clk)); + + assign out_clk = clk; + assign up_drp_rdata[15:0] = 'd0; + assign up_drp_ready = 'd0; + assign up_drp_locked = 'd0; + + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** + diff --git a/src/adi/hdl/library/xilinx/common/ad_serdes_in.v b/src/adi/hdl/library/xilinx/common/ad_serdes_in.v new file mode 100644 index 00000000..aa585b8b --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_serdes_in.v @@ -0,0 +1,197 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ps/1ps + +module ad_serdes_in #( + + parameter DEVICE_TYPE = 0, + parameter DDR_OR_SDR_N = 0, + parameter SERDES_FACTOR = 8, + parameter DATA_WIDTH = 16, + parameter IODELAY_CTRL = 0, + parameter IODELAY_GROUP = "dev_if_delay_group") ( + + // reset and clocks + + input rst, + input clk, + input div_clk, + input loaden, + input [ 7:0] phase, + input locked, + + // data interface + + output [(DATA_WIDTH-1):0] data_s0, + output [(DATA_WIDTH-1):0] data_s1, + output [(DATA_WIDTH-1):0] data_s2, + output [(DATA_WIDTH-1):0] data_s3, + output [(DATA_WIDTH-1):0] data_s4, + output [(DATA_WIDTH-1):0] data_s5, + output [(DATA_WIDTH-1):0] data_s6, + output [(DATA_WIDTH-1):0] data_s7, + input [(DATA_WIDTH-1):0] data_in_p, + input [(DATA_WIDTH-1):0] data_in_n, + + // delay-data interface + + input up_clk, + input [(DATA_WIDTH-1):0] up_dld, + input [((DATA_WIDTH*5)-1):0] up_dwdata, + output [((DATA_WIDTH*5)-1):0] up_drdata, + + // delay-control interface + + input delay_clk, + input delay_rst, + output delay_locked); + + localparam DEVICE_7SERIES = 0; + localparam DATA_RATE = (DDR_OR_SDR_N) ? "DDR" : "SDR"; + + // internal signals + + wire [(DATA_WIDTH-1):0] data_in_ibuf_s; + wire [(DATA_WIDTH-1):0] data_in_idelay_s; + wire [(DATA_WIDTH-1):0] data_shift1_s; + wire [(DATA_WIDTH-1):0] data_shift2_s; + + // delay controller + + generate + if (IODELAY_CTRL == 1) begin + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYCTRL i_delay_ctrl ( + .RST (delay_rst), + .REFCLK (delay_clk), + .RDY (delay_locked)); + end else begin + assign delay_locked = 1'b1; + end + endgenerate + + // received data interface: ibuf -> idelay -> iserdes + + genvar l_inst; + generate if (DEVICE_TYPE == DEVICE_7SERIES) begin + for (l_inst = 0; l_inst <= (DATA_WIDTH-1); l_inst = l_inst + 1) begin: g_data + + IBUFDS i_ibuf ( + .I (data_in_p[l_inst]), + .IB (data_in_n[l_inst]), + .O (data_in_ibuf_s[l_inst])); + + (* IODELAY_GROUP = IODELAY_GROUP *) + IDELAYE2 #( + .CINVCTRL_SEL ("FALSE"), + .DELAY_SRC ("IDATAIN"), + .HIGH_PERFORMANCE_MODE ("FALSE"), + .IDELAY_TYPE ("VAR_LOAD"), + .IDELAY_VALUE (0), + .REFCLK_FREQUENCY (200.0), + .PIPE_SEL ("FALSE"), + .SIGNAL_PATTERN ("DATA")) + i_idelay ( + .CE (1'b0), + .INC (1'b0), + .DATAIN (1'b0), + .LDPIPEEN (1'b0), + .CINVCTRL (1'b0), + .REGRST (1'b0), + .C (up_clk), + .IDATAIN (data_in_ibuf_s[l_inst]), + .DATAOUT (data_in_idelay_s[l_inst]), + .LD (up_dld[l_inst]), + .CNTVALUEIN (up_dwdata[((5*l_inst)+4):(5*l_inst)]), + .CNTVALUEOUT (up_drdata[((5*l_inst)+4):(5*l_inst)])); + + ISERDESE2 #( + .DATA_RATE (DATA_RATE), + .DATA_WIDTH (SERDES_FACTOR), + .DYN_CLKDIV_INV_EN ("FALSE"), + .DYN_CLK_INV_EN ("FALSE"), + .INIT_Q1 (1'b0), + .INIT_Q2 (1'b0), + .INIT_Q3 (1'b0), + .INIT_Q4 (1'b0), + .INTERFACE_TYPE ("NETWORKING"), + .IOBDELAY ("IFD"), + .NUM_CE (2), + .OFB_USED ("FALSE"), + .SERDES_MODE ("MASTER"), + .SRVAL_Q1 (1'b0), + .SRVAL_Q2 (1'b0), + .SRVAL_Q3 (1'b0), + .SRVAL_Q4 (1'b0)) + i_iserdes ( + .O (), + .Q1 (data_s0[l_inst]), + .Q2 (data_s1[l_inst]), + .Q3 (data_s2[l_inst]), + .Q4 (data_s3[l_inst]), + .Q5 (data_s4[l_inst]), + .Q6 (data_s5[l_inst]), + .Q7 (data_s6[l_inst]), + .Q8 (data_s7[l_inst]), + .SHIFTOUT1 (), + .SHIFTOUT2 (), + .BITSLIP (1'b0), + .CE1 (1'b1), + .CE2 (1'b1), + .CLKDIVP (1'b0), + .CLK (clk), + .CLKB (~clk), + .CLKDIV (div_clk), + .OCLK (1'b0), + .DYNCLKDIVSEL (1'b0), + .DYNCLKSEL (1'b0), + .D (1'b0), + .DDLY (data_in_idelay_s[l_inst]), + .OFB (1'b0), + .OCLKB (1'b0), + .RST (rst), + .SHIFTIN1 (1'b0), + .SHIFTIN2 (1'b0)); + end /* g_data */ + + end + endgenerate + + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/src/adi/hdl/library/xilinx/common/ad_serdes_out.v b/src/adi/hdl/library/xilinx/common/ad_serdes_out.v new file mode 100644 index 00000000..354deb7c --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/ad_serdes_out.v @@ -0,0 +1,133 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// serial data output interface: serdes(x8) + +`timescale 1ps/1ps + +module ad_serdes_out #( + + parameter DEVICE_TYPE = 0, + parameter DDR_OR_SDR_N = 1, + parameter SERDES_FACTOR = 8, + parameter DATA_WIDTH = 16) ( + + // reset and clocks + + input rst, + input clk, + input div_clk, + input loaden, + + // data interface + + input [(DATA_WIDTH-1):0] data_s0, + input [(DATA_WIDTH-1):0] data_s1, + input [(DATA_WIDTH-1):0] data_s2, + input [(DATA_WIDTH-1):0] data_s3, + input [(DATA_WIDTH-1):0] data_s4, + input [(DATA_WIDTH-1):0] data_s5, + input [(DATA_WIDTH-1):0] data_s6, + input [(DATA_WIDTH-1):0] data_s7, + output [(DATA_WIDTH-1):0] data_out_se, + output [(DATA_WIDTH-1):0] data_out_p, + output [(DATA_WIDTH-1):0] data_out_n); + + localparam DEVICE_7SERIES = 0; + localparam DR_OQ_DDR = DDR_OR_SDR_N == 1'b1 ? "DDR": "SDR"; + + // internal signals + + wire [(DATA_WIDTH-1):0] data_out_s; + wire [(DATA_WIDTH-1):0] serdes_shift1_s; + wire [(DATA_WIDTH-1):0] serdes_shift2_s; + + assign data_out_se = data_out_s; + + // instantiations + + genvar l_inst; + generate + for (l_inst = 0; l_inst <= (DATA_WIDTH-1); l_inst = l_inst + 1) begin: g_data + + if (DEVICE_TYPE == DEVICE_7SERIES) begin + OSERDESE2 #( + .DATA_RATE_OQ (DR_OQ_DDR), + .DATA_RATE_TQ ("SDR"), + .DATA_WIDTH (SERDES_FACTOR), + .TRISTATE_WIDTH (1), + .SERDES_MODE ("MASTER")) + i_serdes ( + .D1 (data_s0[l_inst]), + .D2 (data_s1[l_inst]), + .D3 (data_s2[l_inst]), + .D4 (data_s3[l_inst]), + .D5 (data_s4[l_inst]), + .D6 (data_s5[l_inst]), + .D7 (data_s6[l_inst]), + .D8 (data_s7[l_inst]), + .T1 (1'b0), + .T2 (1'b0), + .T3 (1'b0), + .T4 (1'b0), + .SHIFTIN1 (1'b0), + .SHIFTIN2 (1'b0), + .SHIFTOUT1 (), + .SHIFTOUT2 (), + .OCE (1'b1), + .CLK (clk), + .CLKDIV (div_clk), + .OQ (data_out_s[l_inst]), + .TQ (), + .OFB (), + .TFB (), + .TBYTEIN (1'b0), + .TBYTEOUT (), + .TCE (1'b0), + .RST (rst)); + end + + OBUFDS i_obuf ( + .I (data_out_s[l_inst]), + .O (data_out_p[l_inst]), + .OB (data_out_n[l_inst])); + + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** + diff --git a/src/adi/hdl/library/xilinx/common/up_clock_mon_constr.xdc b/src/adi/hdl/library/xilinx/common/up_clock_mon_constr.xdc new file mode 100644 index 00000000..e3084923 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/up_clock_mon_constr.xdc @@ -0,0 +1,8 @@ + +set_property ASYNC_REG true [get_cells -hier -filter {name =~ *up_count_running_m*}] +set_property ASYNC_REG true [get_cells -hier -filter {name =~ *d_count_run_m*}] + +set_false_path -from [get_cells -hier -filter {name =~ *d_count_run_m3_reg* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *up_count_running_m1_reg* && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *up_count_run_reg* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *d_count_run_m1_reg* && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *d_count_reg* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *up_d_count_reg* && IS_SEQUENTIAL}] + diff --git a/src/adi/hdl/library/xilinx/common/up_xfer_cntrl_constr.xdc b/src/adi/hdl/library/xilinx/common/up_xfer_cntrl_constr.xdc new file mode 100644 index 00000000..c089f82b --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/up_xfer_cntrl_constr.xdc @@ -0,0 +1,7 @@ + +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *up_xfer_state*}] +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *d_xfer_toggle_m*}] + +set_false_path -from [get_cells -hier -filter {name =~ *d_xfer_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *up_xfer_state_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *up_xfer_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *d_xfer_toggle_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *up_xfer_data* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *d_data_cntrl* && IS_SEQUENTIAL}] diff --git a/src/adi/hdl/library/xilinx/common/up_xfer_status_constr.xdc b/src/adi/hdl/library/xilinx/common/up_xfer_status_constr.xdc new file mode 100644 index 00000000..92231132 --- /dev/null +++ b/src/adi/hdl/library/xilinx/common/up_xfer_status_constr.xdc @@ -0,0 +1,7 @@ + +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *d_xfer_state*}] +set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *up_xfer_toggle_m*}] + +set_false_path -from [get_cells -hier -filter {name =~ *d_xfer_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *up_xfer_toggle_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *up_xfer_toggle_reg && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *d_xfer_state_m1_reg && IS_SEQUENTIAL}] +set_false_path -from [get_cells -hier -filter {name =~ *d_xfer_data* && IS_SEQUENTIAL}] -to [get_cells -hier -filter {name =~ *up_data_status* && IS_SEQUENTIAL}] diff --git a/src/adi/hdl/projects/scripts/adi_board.tcl b/src/adi/hdl/projects/scripts/adi_board.tcl new file mode 100644 index 00000000..ca989459 --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_board.tcl @@ -0,0 +1,763 @@ +################################################################################################### +################################################################################################### + +variable sys_cpu_interconnect_index +variable sys_hp0_interconnect_index +variable sys_hp1_interconnect_index +variable sys_hp2_interconnect_index +variable sys_hp3_interconnect_index +variable sys_mem_interconnect_index + +variable xcvr_index +variable xcvr_tx_index +variable xcvr_rx_index +variable xcvr_instance + +################################################################################################### +################################################################################################### + +set sys_cpu_interconnect_index 0 +set sys_hp0_interconnect_index -1 +set sys_hp1_interconnect_index -1 +set sys_hp2_interconnect_index -1 +set sys_hp3_interconnect_index -1 +set sys_mem_interconnect_index -1 + +set xcvr_index -1 +set xcvr_tx_index 0 +set xcvr_rx_index 0 +set xcvr_instance NONE + +################################################################################################### +################################################################################################### + +proc ad_ip_instance {i_ip i_name {i_params {}}} { + + set cell [create_bd_cell -type ip -vlnv [get_ipdefs -all -filter "VLNV =~ *:${i_ip}:* && \ + design_tool_contexts =~ *IPI* && UPGRADE_VERSIONS == \"\""] ${i_name}] + if {$i_params != {}} { + set config {} + # Add CONFIG. prefix to all config options + foreach {k v} $i_params { + lappend config "CONFIG.$k" $v + } + set_property -dict $config $cell + } +} + +proc ad_ip_parameter {i_name i_param i_value} { + + set_property ${i_param} ${i_value} [get_bd_cells ${i_name}] +} + +################################################################################################### +################################################################################################### + +proc ad_connect_type {p_name} { + + set m_name "" + + if {$m_name eq ""} {set m_name [get_bd_intf_pins -quiet $p_name]} + if {$m_name eq ""} {set m_name [get_bd_pins -quiet $p_name]} + if {$m_name eq ""} {set m_name [get_bd_intf_ports -quiet $p_name]} + if {$m_name eq ""} {set m_name [get_bd_ports -quiet $p_name]} + if {$m_name eq ""} {set m_name [get_bd_intf_nets -quiet $p_name]} + if {$m_name eq ""} {set m_name [get_bd_nets -quiet $p_name]} + + return $m_name +} + +proc ad_connect {p_name_1 p_name_2} { + + if {($p_name_2 eq "GND") || ($p_name_2 eq "VCC")} { + set p_size 1 + set p_msb [get_property left [get_bd_pins $p_name_1]] + set p_lsb [get_property right [get_bd_pins $p_name_1]] + if {($p_msb ne "") && ($p_lsb ne "")} { + set p_size [expr (($p_msb + 1) - $p_lsb)] + } + set p_cell_name "$p_name_2\_$p_size" + if {[get_bd_cells -quiet $p_cell_name] eq ""} { + if {$p_name_2 eq "VCC"} { + set p_value [expr (1 << $p_size) - 1] + } else { + set p_value 0 + } + ad_ip_instance xlconstant $p_cell_name + set_property CONFIG.CONST_WIDTH $p_size [get_bd_cells $p_cell_name] + set_property CONFIG.CONST_VAL $p_value [get_bd_cells $p_cell_name] + } + puts "connect_bd_net $p_cell_name/dout $p_name_1" + connect_bd_net [get_bd_pins $p_name_1] [get_bd_pins $p_cell_name/dout] + return + } + + set m_name_1 [ad_connect_type $p_name_1] + set m_name_2 [ad_connect_type $p_name_2] + + if {$m_name_1 eq ""} { + if {[get_property CLASS $m_name_2] eq "bd_intf_pin"} { + puts "create_bd_intf_net $p_name_1" + create_bd_intf_net $p_name_1 + } + if {[get_property CLASS $m_name_2] eq "bd_pin"} { + puts "create_bd_net $p_name_1" + create_bd_net $p_name_1 + } + set m_name_1 [ad_connect_type $p_name_1] + } + + if {[get_property CLASS $m_name_1] eq "bd_intf_pin"} { + puts "connect_bd_intf_net $m_name_1 $m_name_2" + connect_bd_intf_net $m_name_1 $m_name_2 + return + } + + if {[get_property CLASS $m_name_1] eq "bd_pin"} { + puts "connect_bd_net $m_name_1 $m_name_2" + connect_bd_net $m_name_1 $m_name_2 + return + } + + if {[get_property CLASS $m_name_1] eq "bd_net"} { + puts "connect_bd_net -net $m_name_1 $m_name_2" + connect_bd_net -net $m_name_1 $m_name_2 + return + } +} + +proc ad_disconnect {p_name_1 p_name_2} { + + set m_name_1 [ad_connect_type $p_name_1] + set m_name_2 [ad_connect_type $p_name_2] + + if {[get_property CLASS $m_name_1] eq "bd_net"} { + disconnect_bd_net $m_name_1 $m_name_2 + return + } + + if {[get_property CLASS $m_name_1] eq "bd_port"} { + delete_bd_objs -quiet [get_bd_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_1]] + delete_bd_objs -quiet $m_name_1 + return + } + + if {[get_property CLASS $m_name_1] eq "bd_pin"} { + delete_bd_objs -quiet [get_bd_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_1]] + delete_bd_objs -quiet $m_name_1 + return + } +} + +proc ad_reconct {p_name_1 p_name_2} { + + set m_name_1 [ad_connect_type $p_name_1] + set m_name_2 [ad_connect_type $p_name_2] + + if {[get_property CLASS $m_name_1] eq "bd_pin"} { + delete_bd_objs -quiet [get_bd_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_1]] + delete_bd_objs -quiet [get_bd_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_2]] + } + + if {[get_property CLASS $m_name_1] eq "bd_intf_pin"} { + delete_bd_objs -quiet [get_bd_intf_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_1]] + delete_bd_objs -quiet [get_bd_intf_nets -quiet -of_objects \ + [find_bd_objs -relation connected_to $m_name_2]] + } + + ad_connect $p_name_1 $p_name_2 +} + +################################################################################################### +################################################################################################### + +# +# lane_map maps the logical lane $n onto the physical lane $lane_map[$n]. If no +# lane map is provided logical lane $n is mapped onto physical lane $n. +# +proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {device_clk {}}} { + + global xcvr_index + global xcvr_tx_index + global xcvr_rx_index + global xcvr_instance + + set no_of_lanes [get_property CONFIG.NUM_OF_LANES [get_bd_cells $a_xcvr]] + set qpll_enable [get_property CONFIG.QPLL_ENABLE [get_bd_cells $a_xcvr]] + set tx_or_rx_n [get_property CONFIG.TX_OR_RX_N [get_bd_cells $a_xcvr]] + +# set jesd204_vlnv [get_property VLNV $a_jesd] +# +# if {[string first "analog.com" $jesd204_vlnv] == 0} { +# set jesd204_type 0 +# } elseif {[string first "xilinx.com" $jesd204_vlnv] == 0} { +# set jesd204_type 1 +# } else { +# return -code 1 "Unsupported JESD204 core type." +# } + + set jesd204_bd_type [get_property TYPE [get_bd_cells $a_jesd]] + + if {$jesd204_bd_type == "hier"} { + set jesd204_type 0 + } else { + set jesd204_type 1 + } + + if {$xcvr_instance ne $u_xcvr} { + set xcvr_index [expr ($xcvr_index + 1)] + set xcvr_tx_index 0 + set xcvr_rx_index 0 + set xcvr_instance $u_xcvr + } + + set txrx "rx" + set data_dir "I" + set ctrl_dir "O" + set index $xcvr_rx_index + + if {$tx_or_rx_n == 1} { + + set txrx "tx" + set data_dir "O" + set ctrl_dir "I" + set index $xcvr_tx_index + } + + set m_sysref ${txrx}_sysref_${index} + set m_sync ${txrx}_sync_${index} + set m_data ${txrx}_data + + if {$xcvr_index >= 1} { + + set m_sysref ${txrx}_sysref_${xcvr_index}_${index} + set m_sync ${txrx}_sync_${xcvr_index}_${index} + set m_data ${txrx}_data_${xcvr_index} + } + + if {$jesd204_type == 0} { + set num_of_links [get_property CONFIG.NUM_LINKS [get_bd_cells $a_jesd/$txrx]] + } else { + set num_of_links 1 + } + + create_bd_port -dir I $m_sysref + create_bd_port -from [expr $num_of_links - 1] -to 0 -dir ${ctrl_dir} $m_sync + + if {$device_clk == {}} { + set device_clk ${u_xcvr}/${txrx}_out_clk_${index} + set rst_gen [regsub -all "/" ${a_jesd}_rstgen "_"] + set create_rst_gen 1 + } else { + set rst_gen ${device_clk}_rstgen + # Only create one reset gen per clock + set create_rst_gen [expr {[get_bd_cells -quiet ${rst_gen}] == {}}] + } + + if {${create_rst_gen}} { + ad_ip_instance proc_sys_reset ${rst_gen} + ad_connect ${device_clk} ${rst_gen}/slowest_sync_clk + ad_connect sys_cpu_resetn ${rst_gen}/ext_reset_in + } + + for {set n 0} {$n < $no_of_lanes} {incr n} { + + set m [expr ($n + $index)] + + if {$tx_or_rx_n == 0} { + ad_connect ${a_xcvr}/up_es_${n} ${u_xcvr}/up_es_${m} + if {$jesd204_type == 0} { + ad_connect ${a_jesd}/phy_en_char_align ${u_xcvr}/${txrx}_calign_${m} + } else { + ad_connect ${a_jesd}/rxencommaalign_out ${u_xcvr}/${txrx}_calign_${m} + } + } + + if {(($m%4) == 0) && ($qpll_enable == 1)} { + ad_connect ${a_xcvr}/up_cm_${n} ${u_xcvr}/up_cm_${m} + } + + if {$lane_map != {}} { + set phys_lane [lindex $lane_map $n] + if {$phys_lane != {}} { + set phys_lane [expr $phys_lane + $index] + } + } else { + set phys_lane $m + } + + ad_connect ${a_xcvr}/up_ch_${n} ${u_xcvr}/up_${txrx}_${m} + ad_connect ${device_clk} ${u_xcvr}/${txrx}_clk_${m} + if {$phys_lane != {}} { + if {$jesd204_type == 0} { + ad_connect ${u_xcvr}/${txrx}_${phys_lane} ${a_jesd}/${txrx}_phy${n} + } else { + ad_connect ${u_xcvr}/${txrx}_${phys_lane} ${a_jesd}/gt${n}_${txrx} + } + } + + create_bd_port -dir ${data_dir} ${m_data}_${m}_p + create_bd_port -dir ${data_dir} ${m_data}_${m}_n + ad_connect ${u_xcvr}/${txrx}_${m}_p ${m_data}_${m}_p + ad_connect ${u_xcvr}/${txrx}_${m}_n ${m_data}_${m}_n + } + + if {$jesd204_type == 0} { + ad_connect ${a_jesd}/sysref $m_sysref + ad_connect ${a_jesd}/sync $m_sync + ad_connect ${device_clk} ${a_jesd}/device_clk +# if {$tx_or_rx_n == 0} { +# ad_connect ${a_xcvr}/up_status ${a_jesd}/phy_ready +# } + } else { + ad_connect ${a_jesd}/${txrx}_sysref $m_sysref + ad_connect ${a_jesd}/${txrx}_sync $m_sync + ad_connect ${device_clk} ${a_jesd}/${txrx}_core_clk + ad_connect ${a_xcvr}/up_status ${a_jesd}/${txrx}_reset_done + ad_connect ${rst_gen}/peripheral_reset ${a_jesd}/${txrx}_reset + } + + if {$tx_or_rx_n == 0} { + set xcvr_rx_index [expr ($xcvr_rx_index + $no_of_lanes)] + } + + if {$tx_or_rx_n == 1} { + set xcvr_tx_index [expr ($xcvr_tx_index + $no_of_lanes)] + } +} + +proc ad_xcvrpll {m_src m_dst} { + + foreach p_dst [get_bd_pins -quiet $m_dst] { + connect_bd_net [ad_connect_type $m_src] $p_dst + } +} + +################################################################################################### +################################################################################################### + +proc ad_mem_hp0_interconnect {p_clk p_name} { + + global sys_zynq + + if {($sys_zynq == 0) && ($p_name eq "sys_ps7/S_AXI_HP0")} {return} + if {$sys_zynq == 0} {ad_mem_hpx_interconnect "MEM" $p_clk $p_name} + if {$sys_zynq >= 1} {ad_mem_hpx_interconnect "HP0" $p_clk $p_name} +} + +proc ad_mem_hp1_interconnect {p_clk p_name} { + + global sys_zynq + + if {($sys_zynq == 0) && ($p_name eq "sys_ps7/S_AXI_HP1")} {return} + if {$sys_zynq == 0} {ad_mem_hpx_interconnect "MEM" $p_clk $p_name} + if {$sys_zynq >= 1} {ad_mem_hpx_interconnect "HP1" $p_clk $p_name} +} + +proc ad_mem_hp2_interconnect {p_clk p_name} { + + global sys_zynq + + if {($sys_zynq == 0) && ($p_name eq "sys_ps7/S_AXI_HP2")} {return} + if {$sys_zynq == 0} {ad_mem_hpx_interconnect "MEM" $p_clk $p_name} + if {$sys_zynq >= 1} {ad_mem_hpx_interconnect "HP2" $p_clk $p_name} +} + +proc ad_mem_hp3_interconnect {p_clk p_name} { + + global sys_zynq + + if {($sys_zynq == 0) && ($p_name eq "sys_ps7/S_AXI_HP3")} {return} + if {$sys_zynq == 0} {ad_mem_hpx_interconnect "MEM" $p_clk $p_name} + if {$sys_zynq >= 1} {ad_mem_hpx_interconnect "HP3" $p_clk $p_name} +} + +################################################################################################### +################################################################################################### + +proc ad_mem_hpx_interconnect {p_sel p_clk p_name} { + + global sys_zynq + global sys_ddr_addr_seg + global sys_hp0_interconnect_index + global sys_hp1_interconnect_index + global sys_hp2_interconnect_index + global sys_hp3_interconnect_index + global sys_mem_interconnect_index + + set p_name_int $p_name + set p_clk_source [get_bd_pins -filter {DIR == O} -of_objects [get_bd_nets $p_clk]] + + if {$p_sel eq "MEM"} { + if {$sys_mem_interconnect_index < 0} { + ad_ip_instance axi_interconnect axi_mem_interconnect + } + set m_interconnect_index $sys_mem_interconnect_index + set m_interconnect_cell [get_bd_cells axi_mem_interconnect] + set m_addr_seg [get_bd_addr_segs -of_objects [get_bd_cells axi_ddr_cntrl]] + } + + if {($p_sel eq "HP0") && ($sys_zynq == 1)} { + if {$sys_hp0_interconnect_index < 0} { + set p_name_int sys_ps7/S_AXI_HP0 + set_property CONFIG.PCW_USE_S_AXI_HP0 {1} [get_bd_cells sys_ps7] + ad_ip_instance axi_interconnect axi_hp0_interconnect + } + set m_interconnect_index $sys_hp0_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp0_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps7/S_AXI_HP0/HP0_DDR_LOWOCM] + } + + if {($p_sel eq "HP1") && ($sys_zynq == 1)} { + if {$sys_hp1_interconnect_index < 0} { + set p_name_int sys_ps7/S_AXI_HP1 + set_property CONFIG.PCW_USE_S_AXI_HP1 {1} [get_bd_cells sys_ps7] + ad_ip_instance axi_interconnect axi_hp1_interconnect + } + set m_interconnect_index $sys_hp1_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp1_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps7/S_AXI_HP1/HP1_DDR_LOWOCM] + } + + if {($p_sel eq "HP2") && ($sys_zynq == 1)} { + if {$sys_hp2_interconnect_index < 0} { + set p_name_int sys_ps7/S_AXI_HP2 + set_property CONFIG.PCW_USE_S_AXI_HP2 {1} [get_bd_cells sys_ps7] + ad_ip_instance axi_interconnect axi_hp2_interconnect + } + set m_interconnect_index $sys_hp2_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp2_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps7/S_AXI_HP2/HP2_DDR_LOWOCM] + } + + if {($p_sel eq "HP3") && ($sys_zynq == 1)} { + if {$sys_hp3_interconnect_index < 0} { + set p_name_int sys_ps7/S_AXI_HP3 + set_property CONFIG.PCW_USE_S_AXI_HP3 {1} [get_bd_cells sys_ps7] + ad_ip_instance axi_interconnect axi_hp3_interconnect + } + set m_interconnect_index $sys_hp3_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp3_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps7/S_AXI_HP3/HP3_DDR_LOWOCM] + } + + if {($p_sel eq "HP0") && ($sys_zynq == 2)} { + if {$sys_hp0_interconnect_index < 0} { + set p_name_int sys_ps8/S_AXI_HP0_FPD + set_property CONFIG.PSU__USE__S_AXI_GP2 {1} [get_bd_cells sys_ps8] + ad_ip_instance axi_interconnect axi_hp0_interconnect + } + set m_interconnect_index $sys_hp0_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp0_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps8/S_AXI_HP0_FPD/PLLPD_DDR_LOW] + } + + if {($p_sel eq "HP1") && ($sys_zynq == 2)} { + if {$sys_hp1_interconnect_index < 0} { + set p_name_int sys_ps8/S_AXI_HP1_FPD + set_property CONFIG.PSU__USE__S_AXI_GP3 {1} [get_bd_cells sys_ps8] + ad_ip_instance axi_interconnect axi_hp1_interconnect + } + set m_interconnect_index $sys_hp1_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp1_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps8/S_AXI_HP1_FPD/HP0_DDR_LOW] + } + + if {($p_sel eq "HP2") && ($sys_zynq == 2)} { + if {$sys_hp2_interconnect_index < 0} { + set p_name_int sys_ps8/S_AXI_HP2_FPD + set_property CONFIG.PSU__USE__S_AXI_GP4 {1} [get_bd_cells sys_ps8] + ad_ip_instance axi_interconnect axi_hp2_interconnect + } + set m_interconnect_index $sys_hp2_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp2_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps8/S_AXI_HP2_FPD/HP1_DDR_LOW] + } + + if {($p_sel eq "HP3") && ($sys_zynq == 2)} { + if {$sys_hp3_interconnect_index < 0} { + set p_name_int sys_ps8/S_AXI_HP3_FPD + set_property CONFIG.PSU__USE__S_AXI_GP5 {1} [get_bd_cells sys_ps8] + ad_ip_instance axi_interconnect axi_hp3_interconnect + } + set m_interconnect_index $sys_hp3_interconnect_index + set m_interconnect_cell [get_bd_cells axi_hp3_interconnect] + set m_addr_seg [get_bd_addr_segs sys_ps8/S_AXI_HP3_FPD/HP2_DDR_LOW] + } + + set i_str "S$m_interconnect_index" + if {$m_interconnect_index < 10} { + set i_str "S0$m_interconnect_index" + } + + set m_interconnect_index [expr $m_interconnect_index + 1] + + set p_intf_name [lrange [split $p_name_int "/"] end end] + set p_cell_name [lrange [split $p_name_int "/"] 0 0] + set p_intf_clock [get_bd_pins -filter "TYPE == clk && (CONFIG.ASSOCIATED_BUSIF == ${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ ${p_intf_name}:* || CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name}:*)" -quiet -of_objects [get_bd_cells $p_cell_name]] + if {[find_bd_objs -quiet -relation connected_to $p_intf_clock] ne "" || + $p_intf_clock eq $p_clk_source} { + set p_intf_clock "" + } + + regsub clk $p_clk resetn p_rst + if {[get_bd_nets -quiet $p_rst] eq ""} { + set p_rst sys_cpu_resetn + } + + if {$m_interconnect_index == 0} { + set_property CONFIG.NUM_MI 1 $m_interconnect_cell + set_property CONFIG.NUM_SI 1 $m_interconnect_cell + ad_connect $p_rst $m_interconnect_cell/ARESETN + ad_connect $p_clk $m_interconnect_cell/ACLK + ad_connect $p_rst $m_interconnect_cell/M00_ARESETN + ad_connect $p_clk $m_interconnect_cell/M00_ACLK + ad_connect $m_interconnect_cell/M00_AXI $p_name_int + if {$p_intf_clock ne ""} { + ad_connect $p_clk $p_intf_clock + } + } else { + set_property CONFIG.NUM_SI $m_interconnect_index $m_interconnect_cell + ad_connect $p_rst $m_interconnect_cell/${i_str}_ARESETN + ad_connect $p_clk $m_interconnect_cell/${i_str}_ACLK + ad_connect $m_interconnect_cell/${i_str}_AXI $p_name_int + if {$p_intf_clock ne ""} { + ad_connect $p_clk $p_intf_clock + } + assign_bd_address $m_addr_seg + } + + if {$m_interconnect_index > 1} { + set_property CONFIG.STRATEGY {2} $m_interconnect_cell + } + + if {$p_sel eq "MEM"} {set sys_mem_interconnect_index $m_interconnect_index} + if {$p_sel eq "HP0"} {set sys_hp0_interconnect_index $m_interconnect_index} + if {$p_sel eq "HP1"} {set sys_hp1_interconnect_index $m_interconnect_index} + if {$p_sel eq "HP2"} {set sys_hp2_interconnect_index $m_interconnect_index} + if {$p_sel eq "HP3"} {set sys_hp3_interconnect_index $m_interconnect_index} + +} + +################################################################################################### +################################################################################################### + +proc ad_cpu_interconnect {p_address p_name} { + + global sys_zynq + global sys_cpu_interconnect_index + + set i_str "M$sys_cpu_interconnect_index" + if {$sys_cpu_interconnect_index < 10} { + set i_str "M0$sys_cpu_interconnect_index" + } + + if {$sys_cpu_interconnect_index == 0} { + ad_ip_instance axi_interconnect axi_cpu_interconnect + if {$sys_zynq == 2} { + ad_connect sys_cpu_clk sys_ps8/maxihpm0_lpd_aclk + ad_connect sys_cpu_clk axi_cpu_interconnect/ACLK + ad_connect sys_cpu_clk axi_cpu_interconnect/S00_ACLK + ad_connect sys_cpu_resetn axi_cpu_interconnect/ARESETN + ad_connect sys_cpu_resetn axi_cpu_interconnect/S00_ARESETN + ad_connect axi_cpu_interconnect/S00_AXI sys_ps8/M_AXI_HPM0_LPD + } + if {$sys_zynq == 1} { + ad_connect sys_cpu_clk sys_ps7/M_AXI_GP0_ACLK + ad_connect sys_cpu_clk axi_cpu_interconnect/ACLK + ad_connect sys_cpu_clk axi_cpu_interconnect/S00_ACLK + ad_connect sys_cpu_resetn axi_cpu_interconnect/ARESETN + ad_connect sys_cpu_resetn axi_cpu_interconnect/S00_ARESETN + ad_connect axi_cpu_interconnect/S00_AXI sys_ps7/M_AXI_GP0 + } + if {$sys_zynq == 0} { + ad_connect sys_cpu_clk axi_cpu_interconnect/ACLK + ad_connect sys_cpu_clk axi_cpu_interconnect/S00_ACLK + ad_connect sys_cpu_resetn axi_cpu_interconnect/ARESETN + ad_connect sys_cpu_resetn axi_cpu_interconnect/S00_ARESETN + ad_connect axi_cpu_interconnect/S00_AXI sys_mb/M_AXI_DP + } + } + + if {$sys_zynq == 2} { + set sys_addr_cntrl_space [get_bd_addr_spaces sys_ps8/Data] + } + if {$sys_zynq == 1} { + set sys_addr_cntrl_space [get_bd_addr_spaces sys_ps7/Data] + } + if {$sys_zynq == 0} { + set sys_addr_cntrl_space [get_bd_addr_spaces sys_mb/Data] + } + + set sys_cpu_interconnect_index [expr $sys_cpu_interconnect_index + 1] + + + set p_cell [get_bd_cells $p_name] + set p_intf [get_bd_intf_pins -filter "MODE == Slave && VLNV == xilinx.com:interface:aximm_rtl:1.0"\ + -of_objects $p_cell] + + set p_hier_cell $p_cell + set p_hier_intf $p_intf + + while {$p_hier_intf != "" && [get_property TYPE $p_hier_cell] == "hier"} { + set p_hier_intf [find_bd_objs -boundary_type lower \ + -relation connected_to $p_hier_intf] + if {$p_hier_intf != {}} { + set p_hier_cell [get_bd_cells -of_objects $p_hier_intf] + } else { + set p_hier_cell {} + } + } + + set p_intf_clock "" + set p_intf_reset "" + + if {$p_hier_cell != {}} { + set p_intf_name [lrange [split $p_hier_intf "/"] end end] + + set p_intf_clock [get_bd_pins -filter "TYPE == clk && \ + (CONFIG.ASSOCIATED_BUSIF == ${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ ${p_intf_name}:* || \ + CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name}:*)" \ + -quiet -of_objects $p_hier_cell] + set p_intf_reset [get_bd_pins -filter "TYPE == rst && \ + (CONFIG.ASSOCIATED_BUSIF == ${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ ${p_intf_name}:* || + CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name} || \ + CONFIG.ASSOCIATED_BUSIF =~ *:${p_intf_name}:*)" \ + -quiet -of_objects $p_hier_cell] + + if {($p_intf_clock ne "") && ($p_intf_reset eq "")} { + set p_intf_reset [get_property CONFIG.ASSOCIATED_RESET [get_bd_pins ${p_intf_clock}]] + if {$p_intf_reset ne ""} { + set p_intf_reset [get_bd_pins -filter "NAME == $p_intf_reset" -of_objects $p_hier_cell] + } + } + + # Trace back up + set p_hier_cell2 $p_hier_cell + + while {$p_intf_clock != {} && $p_hier_cell2 != $p_cell && $p_hier_cell2 != {}} { + puts $p_intf_clock + puts $p_hier_cell2 + set p_intf_clock [find_bd_objs -boundary_type upper \ + -relation connected_to $p_intf_clock] + if {$p_intf_clock != {}} { + set p_intf_clock [get_bd_pins [get_property PATH $p_intf_clock]] + set p_hier_cell2 [get_bd_cells -of_objects $p_intf_clock] + } + } + + set p_hier_cell2 $p_hier_cell + + while {$p_intf_reset != {} && $p_hier_cell2 != $p_cell && $p_hier_cell2 != {}} { + set p_intf_reset [find_bd_objs -boundary_type upper \ + -relation connected_to $p_intf_reset] + if {$p_intf_reset != {}} { + set p_intf_reset [get_bd_pins [get_property PATH $p_intf_reset]] + set p_hier_cell2 [get_bd_cells -of_objects $p_intf_reset] + } + } + } + + + if {[find_bd_objs -quiet -relation connected_to $p_intf_clock] ne ""} { + set p_intf_clock "" + } + if {$p_intf_reset ne ""} { + if {[find_bd_objs -quiet -relation connected_to $p_intf_reset] ne ""} { + set p_intf_reset "" + } + } + + set_property CONFIG.NUM_MI $sys_cpu_interconnect_index [get_bd_cells axi_cpu_interconnect] + + ad_connect sys_cpu_clk axi_cpu_interconnect/${i_str}_ACLK + if {$p_intf_clock ne ""} { + ad_connect sys_cpu_clk ${p_intf_clock} + } + ad_connect sys_cpu_resetn axi_cpu_interconnect/${i_str}_ARESETN + if {$p_intf_reset ne ""} { + ad_connect sys_cpu_resetn ${p_intf_reset} + } + ad_connect axi_cpu_interconnect/${i_str}_AXI ${p_intf} + + set p_seg [get_bd_addr_segs -of_objects $p_hier_cell] + set p_index 0 + foreach p_seg_name $p_seg { + if {$p_index == 0} { + set p_seg_range [get_property range $p_seg_name] + if {$p_seg_range < 0x1000} { + set p_seg_range 0x1000 + } + if {$sys_zynq == 2} { + if {($p_address >= 0x40000000) && ($p_address <= 0x4fffffff)} { + set p_address [expr ($p_address + 0x40000000)] + } + if {($p_address >= 0x70000000) && ($p_address <= 0x7fffffff)} { + set p_address [expr ($p_address + 0x20000000)] + } + } + create_bd_addr_seg -range $p_seg_range \ + -offset $p_address $sys_addr_cntrl_space \ + $p_seg_name "SEG_data_${p_name}" + } else { + assign_bd_address $p_seg_name + } + incr p_index + } +} + +################################################################################################### +################################################################################################### + +proc ad_cpu_interrupt {p_ps_index p_mb_index p_name} { + + global sys_zynq + + if {$sys_zynq == 0} {set p_index_int $p_mb_index} + if {$sys_zynq >= 1} {set p_index_int $p_ps_index} + + set p_index [regsub -all {[^0-9]} $p_index_int ""] + set m_index [expr ($p_index - 8)] + + if {($sys_zynq == 2) && ($p_index <= 7)} { + set p_net [get_bd_nets -of_objects [get_bd_pins sys_concat_intc_0/In$p_index]] + set p_pin [get_bd_pins sys_concat_intc_0/In$p_index] + + puts "disconnect_bd_net $p_net $p_pin" + disconnect_bd_net $p_net $p_pin + ad_connect sys_concat_intc_0/In$p_index $p_name + } + + if {($sys_zynq == 2) && ($p_index >= 8)} { + set p_net [get_bd_nets -of_objects [get_bd_pins sys_concat_intc_1/In$m_index]] + set p_pin [get_bd_pins sys_concat_intc_1/In$m_index] + + puts "disconnect_bd_net $p_net $p_pin" + disconnect_bd_net $p_net $p_pin + ad_connect sys_concat_intc_1/In$m_index $p_name + } + + if {$sys_zynq <= 1} { + + set p_net [get_bd_nets -of_objects [get_bd_pins sys_concat_intc/In$p_index]] + set p_pin [get_bd_pins sys_concat_intc/In$p_index] + + puts "disconnect_bd_net $p_net $p_pin" + disconnect_bd_net $p_net $p_pin + ad_connect sys_concat_intc/In$p_index $p_name + } +} + +################################################################################################### +################################################################################################### + diff --git a/src/adi/hdl/projects/scripts/adi_env.tcl b/src/adi/hdl/projects/scripts/adi_env.tcl new file mode 100644 index 00000000..361e8858 --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_env.tcl @@ -0,0 +1,15 @@ + +# environment related stuff + +set ad_hdl_dir [file normalize [file join [file dirname [info script]] "../.."]] +set ad_phdl_dir $ad_hdl_dir + + +if [info exists ::env(ADI_HDL_DIR)] { + set ad_hdl_dir [file normalize $::env(ADI_HDL_DIR)] +} + +if [info exists ::env(ADI_PHDL_DIR)] { + set ad_phdl_dir [file normalize $::env(ADI_PHDL_DIR)] +} + diff --git a/src/adi/hdl/projects/scripts/adi_project.tcl b/src/adi/hdl/projects/scripts/adi_project.tcl new file mode 100644 index 00000000..62d949e2 --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_project.tcl @@ -0,0 +1,289 @@ + +variable p_board +variable p_device +variable sys_zynq +variable p_prcfg_init +variable p_prcfg_list +variable p_prcfg_status + +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2018.2" +} + +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +set p_board "not-applicable" +set p_device "none" +set sys_zynq 1 +set ADI_POWER_OPTIMIZATION 0 + +proc adi_project_xilinx {project_name {mode 0}} { + + global ad_hdl_dir + global ad_phdl_dir + global p_board + global p_device + global sys_zynq + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + + if [regexp "_ac701$" $project_name] { + set p_device "xc7a200tfbg676-2" + set p_board "xilinx.com:ac701:part0:1.0" + set sys_zynq 0 + } + if [regexp "_kc705$" $project_name] { + set p_device "xc7k325tffg900-2" + set p_board "xilinx.com:kc705:part0:1.1" + set sys_zynq 0 + } + if [regexp "_vc707$" $project_name] { + set p_device "xc7vx485tffg1761-2" + set p_board "xilinx.com:vc707:part0:1.1" + set sys_zynq 0 + } + if [regexp "_kcu105$" $project_name] { + set p_device "xcku040-ffva1156-2-e" + set p_board "xilinx.com:kcu105:part0:1.1" + set sys_zynq 0 + } + if [regexp "_zed$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "em.avnet.com:zed:part0:1.3" + set sys_zynq 1 + } + if [regexp "_microzed$" $project_name] { + set p_device "xc7z010clg400-1" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zc702$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "xilinx.com:zc702:part0:1.2" + set sys_zynq 1 + } + if [regexp "_zc706$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "xilinx.com:zc706:part0:1.2" + set sys_zynq 1 + } + if [regexp "_mitx045$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zcu102$" $project_name] { + set p_device "xczu9eg-ffvb1156-2-e" + set p_board "xilinx.com:zcu102:part0:3.2" + set sys_zynq 2 + } + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + if {$mode == 0} { + set project_system_dir "./$project_name.srcs/sources_1/bd/system" + create_project $project_name . -part $p_device -force + } else { + set project_system_dir ".srcs/sources_1/bd/system" + create_project -in_memory -part $p_device + } + + if {$mode == 1} { + file mkdir $project_name.data + } + + if {$p_board ne "not-applicable"} { + set_property board_part $p_board [current_project] + } + + set lib_dirs $ad_hdl_dir/library + if {$ad_hdl_dir ne $ad_phdl_dir} { + lappend lib_dirs $ad_phdl_dir/library + } + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog + + ## Load custom message severity definitions + source $ad_hdl_dir/projects/scripts/adi_xilinx_msg.tcl + + ## In Vivado there is a limit for the number of warnings and errors which are + ## displayed by the tool for a particular error or warning; the default value + ## of this limit is 100. + ## Overrides the default limit to 2000. + set_param messaging.defaultLimit 2000 + + create_bd_design "system" + source system_bd.tcl + + save_bd_design + validate_bd_design + + set_property synth_checkpoint_mode None [get_files $project_system_dir/system.bd] + generate_target {synthesis implementation} [get_files $project_system_dir/system.bd] + make_wrapper -files [get_files $project_system_dir/system.bd] -top + + if {$mode == 0} { + import_files -force -norecurse -fileset sources_1 $project_system_dir/hdl/system_wrapper.v + } else { + write_hwdef -file "$project_name.data/$project_name.hwdef" + } +} + +proc adi_project_files {project_name project_files} { + + add_files -norecurse -fileset sources_1 $project_files + set_property top system_top [current_fileset] +} + +proc adi_project_run {project_name} { + global ADI_POWER_OPTIMIZATION + + launch_runs synth_1 + wait_on_run synth_1 + open_run synth_1 + report_timing_summary -file timing_synth.log + + if {![info exists ::env(ADI_NO_BITSTREAM_COMPRESSION)] && ![info exists ADI_NO_BITSTREAM_COMPRESSION]} { + set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] + } + + if {$ADI_POWER_OPTIMIZATION == 1} { + set_property STEPS.POWER_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] + set_property STEPS.POST_PLACE_POWER_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] + } + + launch_runs impl_1 -to_step write_bitstream + wait_on_run impl_1 + open_run impl_1 + report_timing_summary -file timing_impl.log + + file mkdir $project_name.sdk + + if [expr [get_property SLACK [get_timing_paths]] < 0] { + file copy -force $project_name.runs/impl_1/system_top.sysdef $project_name.sdk/system_top_bad_timing.hdf + } else { + file copy -force $project_name.runs/impl_1/system_top.sysdef $project_name.sdk/system_top.hdf + } + + if [expr [get_property SLACK [get_timing_paths]] < 0] { + return -code error [format "ERROR: Timing Constraints NOT met!"] + } +} + +proc adi_project_synth {project_name prcfg_name hdl_files {xdc_files ""}} { + + global p_device + + set p_prefix "$project_name.data/$project_name" + + if {$prcfg_name eq ""} { + + read_verilog .srcs/sources_1/bd/system/hdl/system_wrapper.v + read_verilog $hdl_files + read_xdc $xdc_files + + synth_design -mode default -top system_top -part $p_device > $p_prefix.synth.rds + write_checkpoint -force $p_prefix.synth.dcp + close_project + + } else { + + create_project -in_memory -part $p_device + read_verilog $hdl_files + synth_design -mode out_of_context -top "prcfg" -part $p_device > $p_prefix.${prcfg_name}_synth.rds + write_checkpoint -force $p_prefix.${prcfg_name}_synth.dcp + close_project + } +} + +proc adi_project_impl {project_name prcfg_name {xdc_files ""}} { + + global p_device + global p_prcfg_init + global p_prcfg_list + global p_prcfg_status + + set p_prefix "$project_name.data/$project_name" + + if {$prcfg_name eq "default"} { + set p_prcfg_status 0 + set p_prcfg_list "" + set p_prcfg_init "$p_prefix.${prcfg_name}_impl.dcp" + file mkdir $project_name.sdk + } + + if {$prcfg_name eq "default"} { + + open_checkpoint $p_prefix.synth.dcp -part $p_device + read_xdc $xdc_files + read_checkpoint -cell i_prcfg $p_prefix.${prcfg_name}_synth.dcp + set_property HD.RECONFIGURABLE 1 [get_cells i_prcfg] + opt_design > $p_prefix.${prcfg_name}_opt.rds + write_debug_probes -force $p_prefix.${prcfg_name}_debug_nets.ltx + place_design > $p_prefix.${prcfg_name}_place.rds + route_design > $p_prefix.${prcfg_name}_route.rds + + } else { + + open_checkpoint $p_prefix.default_impl_bb.dcp -part $p_device + lock_design -level routing + read_checkpoint -cell i_prcfg $p_prefix.${prcfg_name}_synth.dcp + read_xdc $xdc_files + opt_design > $p_prefix.${prcfg_name}_opt.rds + place_design > $p_prefix.${prcfg_name}_place.rds + route_design > $p_prefix.${prcfg_name}_route.rds + } + + write_checkpoint -force $p_prefix.${prcfg_name}_impl.dcp + report_utilization -pblocks pb_prcfg -file $p_prefix.${prcfg_name}_utilization.rpt + report_timing_summary -file $p_prefix.${prcfg_name}_timing_summary.rpt + + if [expr [get_property SLACK [get_timing_paths]] < 0] { + set p_prcfg_status 1 + puts "CRITICAL WARNING: Timing Constraints NOT met ($prcfg_name)!" + } + + write_checkpoint -force -cell i_prcfg $p_prefix.${prcfg_name}_prcfg_impl.dcp + update_design -cell i_prcfg -black_box + write_checkpoint -force $p_prefix.${prcfg_name}_impl_bb.dcp + open_checkpoint $p_prefix.${prcfg_name}_impl.dcp -part $p_device + write_bitstream -force -bin_file -file $p_prefix.${prcfg_name}.bit + write_sysdef -hwdef $p_prefix.hwdef -bitfile $p_prefix.${prcfg_name}.bit -file $p_prefix.${prcfg_name}.hdf + file copy -force $p_prefix.${prcfg_name}.hdf $project_name.sdk/system_top.${prcfg_name}.hdf + + if {$prcfg_name ne "default"} { + lappend p_prcfg_list "$p_prefix.${prcfg_name}_impl.dcp" + } + + if {$prcfg_name eq "default"} { + file copy -force $p_prefix.${prcfg_name}.hdf $project_name.sdk/system_top.hdf + } +} + +proc adi_project_verify {project_name} { + + global p_prcfg_init + global p_prcfg_list + global p_prcfg_status + + set p_prefix "$project_name.data/$project_name" + + pr_verify -full_check -initial $p_prcfg_init \ + -additional $p_prcfg_list \ + -file $p_prefix.prcfg_verify.log + + if {$p_prcfg_status == 1} { + return -code error [format "ERROR: Timing Constraints NOT met!"] + } +} + diff --git a/src/adi/hdl/projects/scripts/adi_project_alt.tcl b/src/adi/hdl/projects/scripts/adi_project_alt.tcl new file mode 100644 index 00000000..2e7bb344 --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_project_alt.tcl @@ -0,0 +1,156 @@ + +variable family +variable device +variable version + +set family "none" +set device "none" +set version "18.0.0" + +proc adi_project_altera {project_name} { + + global ad_hdl_dir + global ad_phdl_dir + global family + global device + global version + global quartus + + if [regexp "_a10gx$" $project_name] { + set family "Arria 10" + set device 10AX115S2F45I1SG + set system_qip_file system_bd/system_bd.qip + } + + if [regexp "_a10soc$" $project_name] { + set family "Arria 10" + set device 10AS066N3F40E2SG + set system_qip_file system_bd/system_bd.qip + } + + if [regexp "_c5soc$" $project_name] { + set family "Cyclone V" + set device 5CSXFC6D6F31C8ES + set system_qip_file system_bd/synthesis/system_bd.qip + } + + if [regexp "de10nano$" $project_name] { + set family "Cyclone V" + set device 5CSEBA6U23I7DK + set system_qip_file system_bd/synthesis/system_bd.qip + } + + if [regexp "_a5soc$" $project_name] { + set family "Arria V" + set device 5ASTFD5K3F40I3ES + set system_qip_file system_bd/synthesis/system_bd.qip + } + + if [regexp "_a5gt$" $project_name] { + set family "Arria V" + set device 5AGTFD7K3F40I3 + set system_qip_file system_bd/synthesis/system_bd.qip + } + + # version check + + set m_version [lindex $quartus(version) 1] + if {[string compare $m_version $version] != 0} { + puts -nonewline "Critical Warning: quartus version mismatch; " + puts -nonewline "expected $version, " + puts -nonewline "got $m_version.\n" + } + + # packages used + + load_package flow + + # project + + project_new $project_name -overwrite + + # library paths + + set ad_lib_folders "$ad_hdl_dir/library/**/*;$ad_phdl_dir/library/**/*" + + set_user_option -name USER_IP_SEARCH_PATHS $ad_lib_folders + set_global_assignment -name IP_SEARCH_PATHS $ad_lib_folders + + # project & qsys + + set_global_assignment -name FAMILY $family + set_global_assignment -name DEVICE $device + + # qsys + + set mmu_enabled 1 + if [info exists ::env(ALT_NIOS_MMU_ENABLED)] { + set mmu_enabled $::env(ALT_NIOS_MMU_ENABLED) + } + + set QFILE [open "system_qsys_script.tcl" "w"] + puts $QFILE "set mmu_enabled $mmu_enabled" + puts $QFILE "set ad_hdl_dir $ad_hdl_dir" + puts $QFILE "set ad_phdl_dir $ad_phdl_dir" + puts $QFILE "package require qsys" + puts $QFILE "set_module_property NAME {system_bd}" + puts $QFILE "set_project_property DEVICE_FAMILY {$family}" + puts $QFILE "set_project_property DEVICE $device" + puts $QFILE "source system_qsys.tcl" + puts $QFILE "set_interconnect_requirement {\$system} {qsys_mm.clockCrossingAdapter} {AUTO}" + puts $QFILE "set_interconnect_requirement {\$system} {qsys_mm.burstAdapterImplementation} {PER_BURST_TYPE_CONVERTER}" + puts $QFILE "set_interconnect_requirement {\$system} {qsys_mm.maxAdditionalLatency} {4}" + puts $QFILE "save_system {system_bd.qsys}" + close $QFILE + + exec -ignorestderr $quartus(quartus_rootpath)/sopc_builder/bin/qsys-script \ + --script=system_qsys_script.tcl + exec -ignorestderr $quartus(quartus_rootpath)/sopc_builder/bin/qsys-generate \ + system_bd.qsys --synthesis=VERILOG --output-directory=system_bd \ + --family=$family --part=$device + + # ignored warnings and such + + set_global_assignment -name MESSAGE_DISABLE 17951 ; ## unused RX channels + set_global_assignment -name MESSAGE_DISABLE 18655 ; ## unused TX channels + set_global_assignment -name MESSAGE_DISABLE 114001 ; ## Time value $x truncated to $y + + # The Merlin cores are especially spammy, lets hope non of these warnings is + # an actual issue... + foreach entity {altera_merlin_axi_master_ni altera_merlin_axi_slave_ni \ + altera_merlin_traffic_limiter altera_merlin_burst_adapter_new} { + ## truncated value + set_instance_assignment -name MESSAGE_DISABLE 10230 -entity $entity + } + ## assigned a value but never read + set_instance_assignment -name MESSAGE_DISABLE 10036 -entity altera_merlin_burst_adapter_new + + # default assignments + + set_global_assignment -name QIP_FILE $system_qip_file + set_global_assignment -name VERILOG_FILE system_top.v + set_global_assignment -name SDC_FILE system_constr.sdc + set_global_assignment -name TOP_LEVEL_ENTITY system_top + + # remove altshift_taps + + set_instance_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF -to * -entity up_xfer_cntrl + set_instance_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF -to * -entity up_xfer_status + set_instance_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF -to * -entity up_clock_mon + set_instance_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF -to * -entity ad_rst + set_instance_assignment -name QII_AUTO_PACKED_REGISTERS OFF -to * -entity up_xfer_cntrl + set_instance_assignment -name QII_AUTO_PACKED_REGISTERS OFF -to * -entity up_xfer_status + set_instance_assignment -name QII_AUTO_PACKED_REGISTERS OFF -to * -entity up_clock_mon + set_instance_assignment -name QII_AUTO_PACKED_REGISTERS OFF -to * -entity ad_rst + + # globals + + set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO + set_global_assignment -name ENABLE_ADVANCED_IO_TIMING ON + set_global_assignment -name USE_TIMEQUEST_TIMING_ANALYZER ON + set_global_assignment -name TIMEQUEST_DO_REPORT_TIMING ON + set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON + set_global_assignment -name TIMEQUEST_REPORT_SCRIPT $ad_hdl_dir/projects/scripts/adi_tquest.tcl + set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION OFF +} + diff --git a/src/adi/hdl/projects/scripts/adi_tquest.tcl b/src/adi/hdl/projects/scripts/adi_tquest.tcl new file mode 100644 index 00000000..be50c76b --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_tquest.tcl @@ -0,0 +1,41 @@ + +report_timing -detail full_path -npaths 20 -setup -file timing_impl.log +report_timing -detail full_path -npaths 20 -hold -append -file timing_impl.log +report_timing -detail full_path -npaths 20 -recovery -append -file timing_impl.log +report_timing -detail full_path -npaths 20 -removal -append -file timing_impl.log + +set worst_path [get_timing_paths -npaths 1 -setup] +foreach_in_collection path $worst_path { + set slack [get_path_info $path -slack] +} + +if {$slack > 0} { + set worst_path [get_timing_paths -npaths 1 -hold] + foreach_in_collection path $worst_path { + set slack [get_path_info $path -slack] + } +} + +if {$slack > 0} { + set worst_path [get_timing_paths -npaths 1 -recovery] + foreach_in_collection path $worst_path { + set slack [get_path_info $path -slack] + } +} + +if {$slack > 0} { + set worst_path [get_timing_paths -npaths 1 -removal] + foreach_in_collection path $worst_path { + set slack [get_path_info $path -slack] + } +} + +if {$slack < 0} { + set sof_files [glob *.sof] + foreach sof_file $sof_files { + set root_sof_file [file rootname $sof_file] + set new_sof_file [append root_sof_file "_timing.sof"] + file rename -force $sof_file $new_sof_file + } + return -code error [format "ERROR: Timing Constraints NOT met!"] +} diff --git a/src/adi/hdl/projects/scripts/adi_xilinx_msg.tcl b/src/adi/hdl/projects/scripts/adi_xilinx_msg.tcl new file mode 100644 index 00000000..212d6e33 --- /dev/null +++ b/src/adi/hdl/projects/scripts/adi_xilinx_msg.tcl @@ -0,0 +1,107 @@ + +################################################################################ +## This file contains all the message severity changes for Vivado 20xx.x.x +## These should reviewed at each release and updated if necessary + +## A MUST: Every severity change must have a well defined and described role +## or purpose, and contains the instance of the original message. The main target +## here is to clean the log file from invalid CRITICAL WARNINGS. +## +## User should never change a CRITICAL WARNING to INFO, just to WARNING! + +## This file is source in two places: +# +## at ~/hdl/library/scripts/adi_ip.tcl +## and +## at ~/hdl/projects/scripts/adi_project.tcl +## +################################################################################ + +################################################################################ +## Tool related messages +## IDs : [Vivado 12-xxxx] +################################################################################ + +## For all projects which has SGMII, the tool presumes that we want ot use the +## eth_avb IP too, and because we don't have any license for it, thoughs out a +## CRITICAL WARNING. Downgrade this critical warning to a simple warning. +set_msg_config -id {Vivado 12-1790} -string "Evaluation features should NOT be used in production systems." -new_severity WARNING + +################################################################################ +## Block Design related messages +## IDs : [BD 41-xxxx] +################################################################################ + +## Temporally disabled - could not find and message with this ID +## set_msg_config -id {BD 41-1348} -new_severity WARNING + +## Reset pin A (associated clock X) is connected to reset source B (associated +## clock Y) -- this is a reset transfer between two clock domain, it should stay +## CRITICAL -- needs to be reviewed +set_msg_config -id {BD 41-1343} -new_severity WARNING + +## The connection to interface pin A is being overridden by the user. This pin +## will not be connected as a part of interface connection B (pin A is part of +## the B interface) +## In the future this should disappear, as we switch to using mostly interfaces +set_msg_config -id {BD 41-1306} -new_severity WARNING + +## Cannot set the parameter XXXXXX. It is read-only. | Parameter does not exist. +## To make sure that each and every IP is configured correctly we push this +## CRITICAL WARNING into the ERRORs domain. +set_msg_config -severity {CRITICAL WARNING} -quiet -id {BD 41-1276} -new_severity ERROR + +################################################################################ +## IP packaging and flow related messages [IP_Flow xx-xxxx] +## IDs : [IP_Flow 19-xxxx] +################################################################################ + +## Temporally disabled - could not find and message with this ID +## set_msg_config -id {IP_Flow 19-1687} -new_severity WARNING + +## If you move the project, the path for repository '~/hdl/library' may become +## invalid. A better location for the repository would be in a path adjacent to +## the project. -- Vivado does not like when library sources are outside the project +## directory. +set_msg_config -id {IP_Flow 19-3656} -new_severity INFO + +## Temporally disabled - could not find and message with this ID +## set_msg_config -id {IP_Flow 19-2999} -new_severity INFO + +## Temporally disabled - could not find and message with this ID +## set_msg_config -id {IP_Flow 19-1654} -new_severity INFO + +## Unrecognized family xxxxxxx. Please verify spelling and reissue command to +## set the supported files. -- the adi_ip.tcl script trying to add all the existent +## family to the supported family list. Apparently Xilinx has some inconsistent +## naming conventions for families. TODO:Maybe we should define exactly the supported +## architectures. +set_msg_config -id {IP_Flow 19-4623} -new_severity INFO + +## IP file '~/hdl/library/common/xxxx.v' appears to be outside of the project area. +## This is similar to 19-3656 +set_msg_config -id {IP_Flow 19-459} -new_severity INFO + +## Temporally disabled - could not find and message with this ID +## set_msg_config -id {filemgmt 20-1763} -new_severity WARNING + +################################################################################ +## Placer related messages +## IDs : [Place 30-xxxx] +################################################################################ + +## Invalid constraint on register */axi_spi/*/IOx_I_REG. It has the property IOB=TRUE, +## but is is not driving or driven by any IO element. -- The AXI_SPI IP after +## 2017.4 has a default constraint which setting the input registers property +## IOB=TRUE, this will cause a CRITICAL WARNING is the interface is not used. +set_msg_config -id {Place 30-73} -string "axi_spi" -new_severity WARNING + +################################################################################ +## Other ID less messages +################################################################################ + +## After Vivado 2017.4, the tool does not like negative DDR_DQS_TO_CLK_DELAY +## values on the DDRx interface, and throw a CRITICAL WARNING. Although a negative +## value is not necessarily invalid, the ZedBoard's interface is working this way. +set_msg_config -string "PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY" -new_severity WARNING + diff --git a/src/adi/hdl/projects/scripts/project-altera.mk b/src/adi/hdl/projects/scripts/project-altera.mk new file mode 100644 index 00000000..8418881f --- /dev/null +++ b/src/adi/hdl/projects/scripts/project-altera.mk @@ -0,0 +1,86 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +#################################################################################### + +# Assumes this file is in projects/scripts/project-altera.mk +HDL_PROJECT_PATH := $(subst scripts/project-altera.mk,,$(lastword $(MAKEFILE_LIST))) +HDL_LIBRARY_PATH := $(HDL_PROJECT_PATH)../library/ + +include $(HDL_PROJECT_PATH)../quiet.mk + +ifeq ($(NIOS2_MMU),) + NIOS2_MMU := 1 +endif + +export ALT_NIOS_MMU_ENABLED := $(NIOS2_MMU) + +ALTERA := quartus_sh --64bit -t + +CLEAN_TARGET += *.log +CLEAN_TARGET += *_INFO.txt +CLEAN_TARGET += *_dump.txt +CLEAN_TARGET += db +CLEAN_TARGET += *.asm.rpt +CLEAN_TARGET += *.done +CLEAN_TARGET += *.eda.rpt +CLEAN_TARGET += *.fit.* +CLEAN_TARGET += *.map.* +CLEAN_TARGET += *.sta.* +CLEAN_TARGET += *.qsf +CLEAN_TARGET += *.qpf +CLEAN_TARGET += *.qws +CLEAN_TARGET += *.sof +CLEAN_TARGET += *.cdf +CLEAN_TARGET += *.sld +CLEAN_TARGET += *.qdf +CLEAN_TARGET += hc_output +CLEAN_TARGET += system_bd +CLEAN_TARGET += hps_isw_handoff +CLEAN_TARGET += hps_sdram_*.csv +CLEAN_TARGET += *ddr3_*.csv +CLEAN_TARGET += incremental_db +CLEAN_TARGET += reconfig_mif +CLEAN_TARGET += *.sopcinfo +CLEAN_TARGET += *.jdi +CLEAN_TARGET += *.pin +CLEAN_TARGET += *_summary.csv +CLEAN_TARGET += *.dpf +CLEAN_TARGET += system_qsys_script.tcl +CLEAN_TARGET += system_bd.qsys +CLEAN_TARGET += .qsys_edit + +M_DEPS += system_top.v +M_DEPS += system_qsys.tcl +M_DEPS += system_project.tcl +M_DEPS += system_constr.sdc +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_tquest.tcl +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_project_alt.tcl +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_env.tcl + +M_DEPS += $(foreach dep,$(LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_altera) + +.PHONY: all lib clean clean-all +all: lib $(PROJECT_NAME).sof + + +clean: + $(call clean, \ + $(CLEAN_TARGET), \ + $(HL)$(PROJECT_NAME)$(NC) project) + +clean-all: clean + @for lib in $(LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} clean; \ + done + +$(PROJECT_NAME).sof: $(M_DEPS) + -rm -rf $(CLEAN_TARGET) + $(call build,\ + $(ALTERA) system_project.tcl, \ + $(PROJECT_NAME)_quartus.log, \ + $(HL)$(PROJECT_NAME)$(NC)) + +lib: + @for lib in $(LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} altera || exit $$?; \ + done diff --git a/src/adi/hdl/projects/scripts/project-toplevel.mk b/src/adi/hdl/projects/scripts/project-toplevel.mk new file mode 100644 index 00000000..ad8dcd8e --- /dev/null +++ b/src/adi/hdl/projects/scripts/project-toplevel.mk @@ -0,0 +1,24 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +#################################################################################### + +# Assumes this file is in projects/scripts/project-toplevel.mk +HDL_PROJECT_PATH := $(subst scripts/project-toplevel.mk,,$(lastword $(MAKEFILE_LIST))) + +include $(HDL_PROJECT_PATH)../quiet.mk + +SUBDIRS := $(dir $(wildcard */Makefile)) + +# Create virtual targets "$project/all", "$project/clean", "$project/clean-all" +SUBDIRS_ALL := $(addsuffix all,$(SUBDIRS)) +SUBDIRS_CLEAN := $(addsuffix clean,$(SUBDIRS)) +SUBDIRS_CLEANALL := $(addsuffix clean-all,$(SUBDIRS)) + +.PHONY: all clean clean-all $(SUBDIRS_ALL) $(SUBDIRS_CLEAN) $(SUBDIRS_CLEANALL) + +all: $(SUBDIRS_ALL) +clean: $(SUBDIRS_CLEAN) +clean-all: $(SUBDIRS_CLEANALL) + +$(SUBDIRS_ALL) $(SUBDIRS_CLEAN) $(SUBDIRS_CLEANALL): + $(MAKE) -C $(@D) $(@F) diff --git a/src/adi/hdl/projects/scripts/project-xilinx.mk b/src/adi/hdl/projects/scripts/project-xilinx.mk new file mode 100644 index 00000000..517de9fd --- /dev/null +++ b/src/adi/hdl/projects/scripts/project-xilinx.mk @@ -0,0 +1,62 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +#################################################################################### + +# Assumes this file is in prpojects/scripts/project-xilinx.mk +HDL_PROJECT_PATH := $(subst scripts/project-xilinx.mk,,$(lastword $(MAKEFILE_LIST))) +HDL_LIBRARY_PATH := $(HDL_PROJECT_PATH)../library/ + +include $(HDL_PROJECT_PATH)../quiet.mk + +VIVADO := vivado -mode batch -source + +CLEAN_TARGET := *.cache +CLEAN_TARGET += *.data +CLEAN_TARGET += *.xpr +CLEAN_TARGET += *.log +CLEAN_TARGET += *.jou +CLEAN_TARGET += xgui +CLEAN_TARGET += *.runs +CLEAN_TARGET += *.srcs +CLEAN_TARGET += *.sdk +CLEAN_TARGET += *.hw +CLEAN_TARGET += *.sim +CLEAN_TARGET += .Xil +CLEAN_TARGET += *.ip_user_files +CLEAN_TARGET += *.str + +# Common dependencies that all projects have +M_DEPS += system_project.tcl +M_DEPS += system_bd.tcl +M_DEPS += $(wildcard system_top*.v) +M_DEPS += $(wildcard system_constr.xdc) # Not all projects have this file +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_project.tcl +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_env.tcl +M_DEPS += $(HDL_PROJECT_PATH)scripts/adi_board.tcl + +M_DEPS += $(foreach dep,$(LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/component.xml) + +.PHONY: all lib clean clean-all +all: lib $(PROJECT_NAME).sdk/system_top.hdf + +clean: + $(call clean, \ + $(CLEAN_TARGET), \ + $(HL)$(PROJECT_NAME)$(NC) project) + +clean-all: clean + @for lib in $(LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} clean; \ + done + +$(PROJECT_NAME).sdk/system_top.hdf: $(M_DEPS) + -rm -rf $(CLEAN_TARGET) + $(call build, \ + $(VIVADO) system_project.tcl, \ + $(PROJECT_NAME)_vivado.log, \ + $(HL)$(PROJECT_NAME)$(NC) project) + +lib: + @for lib in $(LIB_DEPS); do \ + $(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} xilinx || exit $$?; \ + done diff --git a/src/adi/hdl/quiet.mk b/src/adi/hdl/quiet.mk new file mode 100644 index 00000000..051d66f9 --- /dev/null +++ b/src/adi/hdl/quiet.mk @@ -0,0 +1,52 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +#################################################################################### + +ifdef MAKE_TERMOUT + ESC:=$(shell printf '\033') + GREEN:=$(ESC)[1;32m + RED:=$(ESC)[1;31m + HL:=$(ESC)[0;33m + NC:=$(ESC)[0m +else + GREEN:= + RED:= + HL:= + NC:= +endif + +ifneq ($(VERBOSE),1) + MAKEFLAGS += --quiet + + # build - Run a build command + # $(1): Command to execute + # $(2): Logfile name + # $(3): Textual description of the task + define build + @echo -n "Building $(strip $(3)) [$(HL)$(CURDIR)/$(strip $(2))$(NC)] ..." + $(strip $(1)) >> $(strip $(2)) 2>&1; \ + (ERR=$$?; if [ $$ERR = 0 ]; then \ + echo " $(GREEN)OK$(NC)"; \ + else \ + echo " $(RED)FAILED$(NC)"; \ + echo "For details see $(HL)$(CURDIR)/$(strip $(2))$(NC)"; \ + echo ""; \ + fi; exit $$ERR) + endef + + # clean - Run a clean command + # $(1): Files to remove + # $(2): Textural description of the task + define clean + @echo "Cleaning $(strip $(2)) ..." + -rm -rf $(strip $(1)) + endef +else + define build + $(strip $(1)) >> $(strip $(2)) 2>&1 + endef + + define clean + -rm -rf $(strip $(1)) + endef +endif From d9856f58b39fab7ba228bca27ffad8c3ac362978 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 14:33:48 -0400 Subject: [PATCH 15/30] adi: Add Makefile --- src/adi/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/adi/Makefile diff --git a/src/adi/Makefile b/src/adi/Makefile new file mode 100644 index 00000000..5fe235d5 --- /dev/null +++ b/src/adi/Makefile @@ -0,0 +1,14 @@ +LIBRARY := ./hdl/library +IPS := axi_clkgen axi_hdmi_tx axi_spdif_tx + +.PHONY: all clean + +all: + for ip in $(IPS); do \ + make -C $(LIBRARY)/$$ip; \ + done + +clean: + for ip in $(IPS); do \ + make -C $(LIBRARY)/$$ip clean; \ + done From 100a82535cf77535e9555c8d136a96e07ebf5ff9 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 14:51:13 -0400 Subject: [PATCH 16/30] parallella/fpga: Makefile: Build ADI ips --- src/parallella/fpga/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/parallella/fpga/Makefile b/src/parallella/fpga/Makefile index b5cda72e..f5055b0f 100644 --- a/src/parallella/fpga/Makefile +++ b/src/parallella/fpga/Makefile @@ -1,12 +1,14 @@ .PHONY: all clean all: + make -C ../../adi all make -C parallella_base/ all make -C headless_e16_z7010/ all make -C headless_e16_z7020/ all make -C hdmi_e16_z7020/ all clean: + make -C ../../adi clean make -C parallella_base/ clean make -C headless_e16_z7010/ clean make -C headless_e16_z7020/ clean From b2e964deb749e99055bc7c6ed4ea27a36776da68 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 14:51:52 -0400 Subject: [PATCH 17/30] parallella/fpga: Use in-tree ADI IP repo --- src/parallella/fpga/hdmi_e16_z7020/system_params.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl index 0984b25a..96567a44 100644 --- a/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl +++ b/src/parallella/fpga/hdmi_e16_z7020/system_params.tcl @@ -10,7 +10,7 @@ set partname "xc7z020clg400-1" #Paths to all IP blocks to use in Vivado "system.bd" -set ip_repos [list "../parallella_base" "../../../../../parallella-fpga/AdiHDLLib/library"] +set ip_repos [list "../parallella_base" "../../../adi/hdl/library"] #All source files set hdl_files [] From 9a8ad923a4c9ba320d4a456a2c598dee46419fef Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 14:52:42 -0400 Subject: [PATCH 18/30] parallella/fpga: hdmi: Fix too long net name warnings --- .../fpga/hdmi_e16_z7020/system_bd.tcl | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl index cf813b32..bc4f8ab0 100644 --- a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl @@ -371,18 +371,18 @@ proc create_root_design { parentCell } { CONFIG.NUM_MI {4} \ ] $axi_hdmi_intercon - # Create instance: axi_parallella_m_axi_intercon, and set properties - set axi_parallella_m_axi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_m_axi_intercon ] + # Create instance: axi_parallella_m_intercon, and set properties + set axi_parallella_m_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_m_intercon ] set_property -dict [ list \ CONFIG.NUM_MI {1} \ CONFIG.NUM_SI {1} \ - ] $axi_parallella_m_axi_intercon + ] $axi_parallella_m_intercon - # Create instance: axi_parallella_s_axi_intercon, and set properties - set axi_parallella_s_axi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_s_axi_intercon ] + # Create instance: axi_parallella_s_intercon, and set properties + set axi_parallella_s_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_s_intercon ] set_property -dict [ list \ CONFIG.NUM_MI {1} \ - ] $axi_parallella_s_axi_intercon + ] $axi_parallella_s_intercon # Create instance: hdmi_0 create_hier_cell_hdmi_0 [current_bd_instance .] hdmi_0 @@ -817,16 +817,16 @@ proc create_root_design { parentCell } { connect_bd_intf_net -intf_net axi_hdmi_intercon_M01_AXI [get_bd_intf_pins axi_hdmi_intercon/M01_AXI] [get_bd_intf_pins hdmi_0/S_AXI_LITE] connect_bd_intf_net -intf_net axi_hdmi_intercon_M02_AXI [get_bd_intf_pins axi_hdmi_intercon/M02_AXI] [get_bd_intf_pins hdmi_0/s_axi1] connect_bd_intf_net -intf_net axi_hdmi_intercon_M03_AXI [get_bd_intf_pins axi_hdmi_intercon/M03_AXI] [get_bd_intf_pins hdmi_0/s_axi2] - connect_bd_intf_net -intf_net axi_parallella_m_axi_intercon_M00_AXI [get_bd_intf_pins axi_parallella_m_axi_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] - connect_bd_intf_net -intf_net axi_parallella_s_axi_intercon_M00_AXI [get_bd_intf_pins axi_parallella_s_axi_intercon/M00_AXI] [get_bd_intf_pins parallella_base_0/s_axi] + connect_bd_intf_net -intf_net axi_parallella_m_intercon_M00_AXI [get_bd_intf_pins axi_parallella_m_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] + connect_bd_intf_net -intf_net axi_parallella_s_intercon_M00_AXI [get_bd_intf_pins axi_parallella_s_intercon/M00_AXI] [get_bd_intf_pins parallella_base_0/s_axi] connect_bd_intf_net -intf_net hdmi_0_DMA_REQ [get_bd_intf_pins hdmi_0/DMA_REQ] [get_bd_intf_pins processing_system7_0/DMA0_REQ] connect_bd_intf_net -intf_net hdmi_0_M00_AXI [get_bd_intf_pins hdmi_0/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP0] - connect_bd_intf_net -intf_net parallella_base_0_m_axi [get_bd_intf_pins axi_parallella_m_axi_intercon/S00_AXI] [get_bd_intf_pins parallella_base_0/m_axi] + connect_bd_intf_net -intf_net parallella_base_0_m_axi [get_bd_intf_pins axi_parallella_m_intercon/S00_AXI] [get_bd_intf_pins parallella_base_0/m_axi] connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] connect_bd_intf_net -intf_net processing_system7_0_DMA0_ACK [get_bd_intf_pins hdmi_0/DMA_ACK] [get_bd_intf_pins processing_system7_0/DMA0_ACK] connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins axi_hdmi_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP0] - connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP1 [get_bd_intf_pins axi_parallella_s_axi_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP1] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP1 [get_bd_intf_pins axi_parallella_s_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP1] # Create port connections connect_bd_net -net hdmi_0_hdmi_16_data [get_bd_ports hdmi_d] [get_bd_pins hdmi_0/hdmi_16_data] @@ -859,9 +859,9 @@ proc create_root_design { parentCell } { connect_bd_net -net parallella_base_0_txo_frame_p [get_bd_ports txo_frame_p] [get_bd_pins parallella_base_0/txo_frame_p] connect_bd_net -net parallella_base_0_txo_lclk_n [get_bd_ports txo_lclk_n] [get_bd_pins parallella_base_0/txo_lclk_n] connect_bd_net -net parallella_base_0_txo_lclk_p [get_bd_ports txo_lclk_p] [get_bd_pins parallella_base_0/txo_lclk_p] - connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins axi_hdmi_intercon/ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/ARESETN] [get_bd_pins proc_sys_reset_0/interconnect_aresetn] - connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins axi_hdmi_intercon/M00_ARESETN] [get_bd_pins axi_hdmi_intercon/M01_ARESETN] [get_bd_pins axi_hdmi_intercon/M02_ARESETN] [get_bd_pins axi_hdmi_intercon/M03_ARESETN] [get_bd_pins axi_hdmi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/M00_ARESETN] [get_bd_pins axi_parallella_m_axi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/M00_ARESETN] [get_bd_pins axi_parallella_s_axi_intercon/S00_ARESETN] [get_bd_pins hdmi_0/axi_resetn] [get_bd_pins parallella_base_0/m_axi_aresetn] [get_bd_pins parallella_base_0/s_axi_aresetn] [get_bd_pins parallella_base_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] - connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_hdmi_intercon/ACLK] [get_bd_pins axi_hdmi_intercon/M00_ACLK] [get_bd_pins axi_hdmi_intercon/M01_ACLK] [get_bd_pins axi_hdmi_intercon/M02_ACLK] [get_bd_pins axi_hdmi_intercon/M03_ACLK] [get_bd_pins axi_hdmi_intercon/S00_ACLK] [get_bd_pins axi_parallella_m_axi_intercon/ACLK] [get_bd_pins axi_parallella_m_axi_intercon/M00_ACLK] [get_bd_pins axi_parallella_m_axi_intercon/S00_ACLK] [get_bd_pins axi_parallella_s_axi_intercon/ACLK] [get_bd_pins axi_parallella_s_axi_intercon/M00_ACLK] [get_bd_pins axi_parallella_s_axi_intercon/S00_ACLK] [get_bd_pins hdmi_0/s_axi_aclk] [get_bd_pins parallella_base_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/DMA0_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP1_ACLK] + connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins axi_hdmi_intercon/ARESETN] [get_bd_pins axi_parallella_m_intercon/ARESETN] [get_bd_pins axi_parallella_s_intercon/ARESETN] [get_bd_pins proc_sys_reset_0/interconnect_aresetn] + connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins axi_hdmi_intercon/M00_ARESETN] [get_bd_pins axi_hdmi_intercon/M01_ARESETN] [get_bd_pins axi_hdmi_intercon/M02_ARESETN] [get_bd_pins axi_hdmi_intercon/M03_ARESETN] [get_bd_pins axi_hdmi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_m_intercon/M00_ARESETN] [get_bd_pins axi_parallella_m_intercon/S00_ARESETN] [get_bd_pins axi_parallella_s_intercon/M00_ARESETN] [get_bd_pins axi_parallella_s_intercon/S00_ARESETN] [get_bd_pins hdmi_0/axi_resetn] [get_bd_pins parallella_base_0/m_axi_aresetn] [get_bd_pins parallella_base_0/s_axi_aresetn] [get_bd_pins parallella_base_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_hdmi_intercon/ACLK] [get_bd_pins axi_hdmi_intercon/M00_ACLK] [get_bd_pins axi_hdmi_intercon/M01_ACLK] [get_bd_pins axi_hdmi_intercon/M02_ACLK] [get_bd_pins axi_hdmi_intercon/M03_ACLK] [get_bd_pins axi_hdmi_intercon/S00_ACLK] [get_bd_pins axi_parallella_m_intercon/ACLK] [get_bd_pins axi_parallella_m_intercon/M00_ACLK] [get_bd_pins axi_parallella_m_intercon/S00_ACLK] [get_bd_pins axi_parallella_s_intercon/ACLK] [get_bd_pins axi_parallella_s_intercon/M00_ACLK] [get_bd_pins axi_parallella_s_intercon/S00_ACLK] [get_bd_pins hdmi_0/s_axi_aclk] [get_bd_pins parallella_base_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/DMA0_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP1_ACLK] connect_bd_net -net processing_system7_0_FCLK_CLK2 [get_bd_pins hdmi_0/clk] [get_bd_pins processing_system7_0/FCLK_CLK2] connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins proc_sys_reset_0/ext_reset_in] [get_bd_pins processing_system7_0/FCLK_RESET0_N] connect_bd_net -net processing_system7_0_GPIO_O [get_bd_pins parallella_base_0/ps_gpio_o] [get_bd_pins processing_system7_0/GPIO_O] From a69142d54f35210cf31406cacf5233679b903576 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 15:28:10 -0400 Subject: [PATCH 19/30] parallella/fpga: Add hdmi_e16_z7010 project Import from github.com/peteasa/parallella-fpga.git H/T @peteasa ! TODO: Not tested! Replace AXI_VDMA with axi_dmac from analogdevicesinc/hdl See this in analogdevices/hdl commit for info commit a0e3997687a32933c0bef3e255430199a5e8c3c1 Author: AndreiGrozav Date: Fri May 11 18:42:59 2018 +0300 common/zed_system_bd.tcl: Replace VDMA Replace Xilinx VDMA IP with ADI axi_dmac IP. --- src/parallella/fpga/Makefile | 2 + src/parallella/fpga/hdmi_e16_z7010/Makefile | 34 + .../fpga/hdmi_e16_z7010/bit2bin.bif | 6 + src/parallella/fpga/hdmi_e16_z7010/build.sh | 6 + src/parallella/fpga/hdmi_e16_z7010/run.tcl | 12 + .../fpga/hdmi_e16_z7010/system_bd.tcl | 918 ++++++++++++++++++ .../fpga/hdmi_e16_z7010/system_params.tcl | 27 + 7 files changed, 1005 insertions(+) create mode 100644 src/parallella/fpga/hdmi_e16_z7010/Makefile create mode 100644 src/parallella/fpga/hdmi_e16_z7010/bit2bin.bif create mode 100644 src/parallella/fpga/hdmi_e16_z7010/build.sh create mode 100644 src/parallella/fpga/hdmi_e16_z7010/run.tcl create mode 100644 src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl create mode 100644 src/parallella/fpga/hdmi_e16_z7010/system_params.tcl diff --git a/src/parallella/fpga/Makefile b/src/parallella/fpga/Makefile index f5055b0f..9e079a13 100644 --- a/src/parallella/fpga/Makefile +++ b/src/parallella/fpga/Makefile @@ -5,6 +5,7 @@ all: make -C parallella_base/ all make -C headless_e16_z7010/ all make -C headless_e16_z7020/ all + make -C hdmi_e16_z7010/ all make -C hdmi_e16_z7020/ all clean: @@ -12,4 +13,5 @@ clean: make -C parallella_base/ clean make -C headless_e16_z7010/ clean make -C headless_e16_z7020/ clean + make -C hdmi_e16_z7010/ clean make -C hdmi_e16_z7020/ clean diff --git a/src/parallella/fpga/hdmi_e16_z7010/Makefile b/src/parallella/fpga/hdmi_e16_z7010/Makefile new file mode 100644 index 00000000..8442c3b8 --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/Makefile @@ -0,0 +1,34 @@ + +M_DEPS := run.tcl +M_DEPS += ../parallella_base/parallella_base.xpr +M_DEPS += ../parallella_base/run.tcl + +M_VIVADO := vivado -mode batch -source + +M_FLIST := *.cache +M_FLIST += *.data +M_FLIST += *.xpr +M_FLIST += *.log +M_FLIST += *.jou +M_FLIST += xgui +M_FLIST += *.runs +M_FLIST += *.srcs +M_FLIST += *.sdk +M_FLIST += .Xil +M_FLIST += parallella_e16_hdmi_gpiose_7021.bit.bin +M_FLIST += system_wrapper.bit.bin +M_FLIST += reports +M_FLIST += results +M_FLIST += system.hw +M_FLIST += system.ip_user_files + +.PHONY: all clean + +all: $(M_DEPS) + rm -f system_wrapper.bit.bin bit2bin.bin + $(M_VIVADO) run.tcl + bootgen -image bit2bin.bif -split bin + cp -f system_wrapper.bit.bin parallella_e16_hdmi_gpiose_7010.bit.bin + +clean: + rm -rf $(M_FLIST) diff --git a/src/parallella/fpga/hdmi_e16_z7010/bit2bin.bif b/src/parallella/fpga/hdmi_e16_z7010/bit2bin.bif new file mode 100644 index 00000000..df3de64e --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/bit2bin.bif @@ -0,0 +1,6 @@ +the_ROM_image: +{ + [bootloader]dummy.elf + ./system.runs/impl_1/system_wrapper.bit +} + diff --git a/src/parallella/fpga/hdmi_e16_z7010/build.sh b/src/parallella/fpga/hdmi_e16_z7010/build.sh new file mode 100644 index 00000000..8ceb1649 --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +rm system_wrapper.bit.bin bit2bin.bin +vivado -mode batch -source run.tcl +bootgen -image bit2bin.bif -split bin +cp system_wrapper.bit.bin parallella_e16_hdmi_gpiose_7010.bit.bin +#archive results based on time stamp diff --git a/src/parallella/fpga/hdmi_e16_z7010/run.tcl b/src/parallella/fpga/hdmi_e16_z7010/run.tcl new file mode 100644 index 00000000..0ab34afc --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/run.tcl @@ -0,0 +1,12 @@ + +#STEP1: DEFINE KEY PARAMETERS +source ./system_params.tcl + +#STEP2: CREATE PROJECT AND READ IN FILES +source ../../../common/fpga/system_init.tcl + +#STEP 3 (OPTIONAL): EDIT system.bd in VIVADO gui, then go to STEP 4. +##... + +#STEP 4: SYNTEHSIZE AND CREATE BITSTRAM +source ../../../common/fpga/system_build.tcl diff --git a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl new file mode 100644 index 00000000..67db1bb3 --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl @@ -0,0 +1,918 @@ + +################################################################ +# This is a generated script based on design: system +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source system_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z010clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name system + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +www.parallella.org:user:parallella_base:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:ip:xlconcat:2.1\ +analog.com:user:axi_clkgen:1.0\ +analog.com:user:axi_hdmi_tx:1.0\ +analog.com:user:axi_spdif_tx:1.0\ +xilinx.com:ip:axi_vdma:6.3\ +xilinx.com:ip:clk_wiz:6.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + +# Hierarchical cell: hdmi_0 +proc create_hier_cell_hdmi_0 { parentCell nameHier } { + + variable script_folder + + if { $parentCell eq "" || $nameHier eq "" } { + catch {common::send_msg_id "BD_TCL-102" "ERROR" "create_hier_cell_hdmi_0() - Empty argument(s)!"} + return + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + # Create cell and set as current instance + set hier_obj [create_bd_cell -type hier $nameHier] + current_bd_instance $hier_obj + + # Create interface pins + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:axis_rtl:1.0 DMA_ACK + create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:axis_rtl:1.0 DMA_REQ + create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 M00_AXI + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI_LITE + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 s_axi1 + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 s_axi2 + + # Create pins + create_bd_pin -dir I -from 0 -to 0 -type rst axi_resetn + create_bd_pin -dir I clk + create_bd_pin -dir O -from 15 -to 0 hdmi_16_data + create_bd_pin -dir O hdmi_16_data_e + create_bd_pin -dir O hdmi_16_hsync + create_bd_pin -dir O hdmi_16_vsync + create_bd_pin -dir O -type clk hdmi_out_clk + create_bd_pin -dir O -type intr mm2s_introut + create_bd_pin -dir I -type clk s_axi_aclk + create_bd_pin -dir O spdif_tx_o + + # Create instance: axi_clkgen_0, and set properties + set axi_clkgen_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_clkgen:1.0 axi_clkgen_0 ] + + # Create instance: axi_hdmi_tx_0, and set properties + set axi_hdmi_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_hdmi_tx:1.0 axi_hdmi_tx_0 ] + + # Create instance: axi_interconnect_0, and set properties + set axi_interconnect_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_interconnect_0 ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_interconnect_0 + + # Create instance: axi_spdif_tx_0, and set properties + set axi_spdif_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_spdif_tx:1.0 axi_spdif_tx_0 ] + set_property -dict [ list \ + CONFIG.DMA_TYPE {1} \ + CONFIG.S_AXI_ADDRESS_WIDTH {16} \ + ] $axi_spdif_tx_0 + + # Create instance: axi_vdma_0, and set properties + set axi_vdma_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_vdma:6.3 axi_vdma_0 ] + set_property -dict [ list \ + CONFIG.c_include_s2mm {0} \ + CONFIG.c_m_axis_mm2s_tdata_width {64} \ + CONFIG.c_use_mm2s_fsync {1} \ + ] $axi_vdma_0 + + # Create instance: clk_wiz_0, and set properties + set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] + set_property -dict [ list \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.CLKOUT1_DRIVES {BUFG} \ + CONFIG.CLKOUT1_JITTER {307.609} \ + CONFIG.CLKOUT1_PHASE_ERROR {262.479} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {12.288} \ + CONFIG.CLKOUT2_DRIVES {BUFG} \ + CONFIG.CLKOUT3_DRIVES {BUFG} \ + CONFIG.CLKOUT4_DRIVES {BUFG} \ + CONFIG.CLKOUT5_DRIVES {BUFG} \ + CONFIG.CLKOUT6_DRIVES {BUFG} \ + CONFIG.CLKOUT7_DRIVES {BUFG} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {47} \ + CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {85} \ + CONFIG.MMCM_COMPENSATION {ZHOLD} \ + CONFIG.MMCM_DIVCLK_DIVIDE {9} \ + CONFIG.PRIMITIVE {PLL} \ + CONFIG.PRIM_IN_FREQ {200} \ + CONFIG.RESET_PORT {resetn} \ + CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.USE_LOCKED {false} \ + ] $clk_wiz_0 + + # Create interface connections + connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] + connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] + connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_vdma_0/S_AXI_LITE] + connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] + connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] + connect_bd_intf_net -intf_net axi_vdma_0_M_AXI_MM2S [get_bd_intf_pins axi_interconnect_0/S00_AXI] [get_bd_intf_pins axi_vdma_0/M_AXI_MM2S] + connect_bd_intf_net -intf_net s_axi1_1 [get_bd_intf_pins s_axi1] [get_bd_intf_pins axi_clkgen_0/s_axi] + connect_bd_intf_net -intf_net s_axi2_1 [get_bd_intf_pins s_axi2] [get_bd_intf_pins axi_hdmi_tx_0/s_axi] + + # Create port connections + connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] + connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] + connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] + connect_bd_net -net axi_hdmi_tx_0_vdma_fs [get_bd_pins axi_vdma_0/mm2s_fsync] + connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_hdmi_tx_0/vdma_ready] [get_bd_pins axi_vdma_0/m_axis_mm2s_tready] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins axi_vdma_0/axi_resetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] + connect_bd_net -net axi_vdma_0_m_axis_mm2s_tdata [get_bd_pins axi_hdmi_tx_0/vdma_data] [get_bd_pins axi_vdma_0/m_axis_mm2s_tdata] + connect_bd_net -net axi_vdma_0_m_axis_mm2s_tvalid [get_bd_pins axi_hdmi_tx_0/vdma_valid] [get_bd_pins axi_vdma_0/m_axis_mm2s_tvalid] + connect_bd_net -net axi_vdma_0_mm2s_introut [get_bd_pins mm2s_introut] [get_bd_pins axi_vdma_0/mm2s_introut] + connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] + connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] + connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] [get_bd_pins axi_vdma_0/m_axi_mm2s_aclk] [get_bd_pins axi_vdma_0/m_axis_mm2s_aclk] [get_bd_pins axi_vdma_0/s_axi_lite_aclk] + + # Restore current instance + current_bd_instance $oldCurInst +} + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set cclk_n [ create_bd_port -dir O cclk_n ] + set cclk_p [ create_bd_port -dir O cclk_p ] + set chip_nreset [ create_bd_port -dir O chip_nreset ] + set gpio_n [ create_bd_port -dir IO -from 11 -to 0 gpio_n ] + set gpio_p [ create_bd_port -dir IO -from 11 -to 0 gpio_p ] + set hdmi_clk [ create_bd_port -dir O -type clk hdmi_clk ] + set hdmi_d [ create_bd_port -dir O -from 15 -to 0 hdmi_d ] + set hdmi_de [ create_bd_port -dir O hdmi_de ] + set hdmi_hsync [ create_bd_port -dir O hdmi_hsync ] + set hdmi_int [ create_bd_port -dir I hdmi_int ] + set hdmi_spdif [ create_bd_port -dir O hdmi_spdif ] + set hdmi_vsync [ create_bd_port -dir O hdmi_vsync ] + set i2c_scl [ create_bd_port -dir IO i2c_scl ] + set i2c_sda [ create_bd_port -dir IO i2c_sda ] + set rxi_data_n [ create_bd_port -dir I -from 7 -to 0 rxi_data_n ] + set rxi_data_p [ create_bd_port -dir I -from 7 -to 0 rxi_data_p ] + set rxi_frame_n [ create_bd_port -dir I rxi_frame_n ] + set rxi_frame_p [ create_bd_port -dir I rxi_frame_p ] + set rxi_lclk_n [ create_bd_port -dir I rxi_lclk_n ] + set rxi_lclk_p [ create_bd_port -dir I rxi_lclk_p ] + set rxo_rd_wait_n [ create_bd_port -dir O rxo_rd_wait_n ] + set rxo_rd_wait_p [ create_bd_port -dir O rxo_rd_wait_p ] + set rxo_wr_wait_n [ create_bd_port -dir O rxo_wr_wait_n ] + set rxo_wr_wait_p [ create_bd_port -dir O rxo_wr_wait_p ] + set txi_rd_wait_n [ create_bd_port -dir I txi_rd_wait_n ] + set txi_rd_wait_p [ create_bd_port -dir I txi_rd_wait_p ] + set txi_wr_wait_n [ create_bd_port -dir I txi_wr_wait_n ] + set txi_wr_wait_p [ create_bd_port -dir I txi_wr_wait_p ] + set txo_data_n [ create_bd_port -dir O -from 7 -to 0 txo_data_n ] + set txo_data_p [ create_bd_port -dir O -from 7 -to 0 txo_data_p ] + set txo_frame_n [ create_bd_port -dir O txo_frame_n ] + set txo_frame_p [ create_bd_port -dir O txo_frame_p ] + set txo_lclk_n [ create_bd_port -dir O txo_lclk_n ] + set txo_lclk_p [ create_bd_port -dir O txo_lclk_p ] + + # Create instance: axi_hdmi_intercon, and set properties + set axi_hdmi_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_hdmi_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {4} \ + ] $axi_hdmi_intercon + + # Create instance: axi_parallella_m_intercon, and set properties + set axi_parallella_m_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_m_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + CONFIG.NUM_SI {1} \ + ] $axi_parallella_m_intercon + + # Create instance: axi_parallella_s_intercon, and set properties + set axi_parallella_s_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_parallella_s_intercon ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + ] $axi_parallella_s_intercon + + # Create instance: hdmi_0 + create_hier_cell_hdmi_0 [current_bd_instance .] hdmi_0 + + # Create instance: parallella_base_0, and set properties + set parallella_base_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_base:1.0 parallella_base_0 ] + set_property -dict [ list \ + CONFIG.NGPIO {12} \ + ] $parallella_base_0 + + # Create instance: proc_sys_reset_0, and set properties + set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ] + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {666.666687} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.062893} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {40} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {200000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1333.333} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {53} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {3} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {48} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1600.000} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {4} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x3FFFFFFF} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {EMIO} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {1} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {1} \ + CONFIG.PCW_EN_EMIO_I2C0 {1} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {1} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_SDIO1 {1} \ + CONFIG.PCW_EN_UART1 {1} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {1} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {152} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {20} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {64} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {1} \ + CONFIG.PCW_I2C0_GRP_INT_IO {EMIO} \ + CONFIG.PCW_I2C0_I2C0_IO {EMIO} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {111.111115} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {30} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {1} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {inout} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {inout} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {in} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {out} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {in} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {inout} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {inout} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {in} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {inout} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {in} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#UART 1#UART 1#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO#GPIO} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#tx#rx#data[0]#cmd#clk#data[1]#data[2]#data[3]#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#gpio[52]#gpio[53]} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {400.000000} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} \ + CONFIG.PCW_UIPARAM_DDR_CL {9} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {9} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {60} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {9} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {9} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {0} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_USB1_IO {MIO 40 .. 51} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_DMA0 {1} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {1} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {1} \ + CONFIG.PCW_USE_S_AXI_HP0 {1} \ + CONFIG.PCW_USE_S_AXI_HP1 {1} \ + ] $processing_system7_0 + + # Create instance: sys_concat_intc, and set properties + set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ] + set_property -dict [ list \ + CONFIG.NUM_PORTS {16} \ + ] $sys_concat_intc + + # Create interface connections + connect_bd_intf_net -intf_net axi_hdmi_intercon_M00_AXI [get_bd_intf_pins axi_hdmi_intercon/M00_AXI] [get_bd_intf_pins hdmi_0/S_AXI] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M01_AXI [get_bd_intf_pins axi_hdmi_intercon/M01_AXI] [get_bd_intf_pins hdmi_0/S_AXI_LITE] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M02_AXI [get_bd_intf_pins axi_hdmi_intercon/M02_AXI] [get_bd_intf_pins hdmi_0/s_axi1] + connect_bd_intf_net -intf_net axi_hdmi_intercon_M03_AXI [get_bd_intf_pins axi_hdmi_intercon/M03_AXI] [get_bd_intf_pins hdmi_0/s_axi2] + connect_bd_intf_net -intf_net axi_parallella_m_intercon_M00_AXI [get_bd_intf_pins axi_parallella_m_intercon/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP1] + connect_bd_intf_net -intf_net axi_parallella_s_intercon_M00_AXI [get_bd_intf_pins axi_parallella_s_intercon/M00_AXI] [get_bd_intf_pins parallella_base_0/s_axi] + connect_bd_intf_net -intf_net hdmi_0_DMA_REQ [get_bd_intf_pins hdmi_0/DMA_REQ] [get_bd_intf_pins processing_system7_0/DMA0_REQ] + connect_bd_intf_net -intf_net hdmi_0_M00_AXI [get_bd_intf_pins hdmi_0/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP0] + connect_bd_intf_net -intf_net parallella_base_0_m_axi [get_bd_intf_pins axi_parallella_m_intercon/S00_AXI] [get_bd_intf_pins parallella_base_0/m_axi] + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_DMA0_ACK [get_bd_intf_pins hdmi_0/DMA_ACK] [get_bd_intf_pins processing_system7_0/DMA0_ACK] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins axi_hdmi_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP0] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP1 [get_bd_intf_pins axi_parallella_s_intercon/S00_AXI] [get_bd_intf_pins processing_system7_0/M_AXI_GP1] + + # Create port connections + connect_bd_net -net hdmi_0_hdmi_16_data [get_bd_ports hdmi_d] [get_bd_pins hdmi_0/hdmi_16_data] + connect_bd_net -net hdmi_0_hdmi_16_data_e [get_bd_ports hdmi_de] [get_bd_pins hdmi_0/hdmi_16_data_e] + connect_bd_net -net hdmi_0_hdmi_16_hsync [get_bd_ports hdmi_hsync] [get_bd_pins hdmi_0/hdmi_16_hsync] + connect_bd_net -net hdmi_0_hdmi_16_vsync [get_bd_ports hdmi_vsync] [get_bd_pins hdmi_0/hdmi_16_vsync] + connect_bd_net -net hdmi_0_hdmi_out_clk [get_bd_ports hdmi_clk] [get_bd_pins hdmi_0/hdmi_out_clk] + connect_bd_net -net hdmi_0_int [get_bd_ports hdmi_int] [get_bd_pins sys_concat_intc/In14] + connect_bd_net -net hdmi_0_mm2s_introut [get_bd_pins hdmi_0/mm2s_introut] [get_bd_pins sys_concat_intc/In15] + connect_bd_net -net hdmi_0_spdif_tx_o1 [get_bd_ports hdmi_spdif] [get_bd_pins hdmi_0/spdif_tx_o] + connect_bd_net -net parallella_base_0_cclk_n [get_bd_ports cclk_n] [get_bd_pins parallella_base_0/cclk_n] + connect_bd_net -net parallella_base_0_cclk_p [get_bd_ports cclk_p] [get_bd_pins parallella_base_0/cclk_p] + connect_bd_net -net parallella_base_0_chip_resetb [get_bd_ports chip_nreset] [get_bd_pins parallella_base_0/chip_nreset] + connect_bd_net -net parallella_base_0_constant_zero [get_bd_pins parallella_base_0/constant_zero] [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In9] [get_bd_pins sys_concat_intc/In10] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] + connect_bd_net -net parallella_base_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_base_0/gpio_n] + connect_bd_net -net parallella_base_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_base_0/gpio_p] + connect_bd_net -net parallella_base_0_i2c_scl [get_bd_ports i2c_scl] [get_bd_pins parallella_base_0/i2c_scl] + connect_bd_net -net parallella_base_0_i2c_scl_i [get_bd_pins parallella_base_0/i2c_scl_i] [get_bd_pins processing_system7_0/I2C0_SCL_I] + connect_bd_net -net parallella_base_0_i2c_sda [get_bd_ports i2c_sda] [get_bd_pins parallella_base_0/i2c_sda] + connect_bd_net -net parallella_base_0_i2c_sda_i [get_bd_pins parallella_base_0/i2c_sda_i] [get_bd_pins processing_system7_0/I2C0_SDA_I] + connect_bd_net -net parallella_base_0_mailbox_irq [get_bd_pins parallella_base_0/mailbox_irq] [get_bd_pins sys_concat_intc/In11] + connect_bd_net -net parallella_base_0_ps_gpio_i [get_bd_pins parallella_base_0/ps_gpio_i] [get_bd_pins processing_system7_0/GPIO_I] + connect_bd_net -net parallella_base_0_rxo_rd_wait_n [get_bd_ports rxo_rd_wait_n] [get_bd_pins parallella_base_0/rxo_rd_wait_n] + connect_bd_net -net parallella_base_0_rxo_rd_wait_p [get_bd_ports rxo_rd_wait_p] [get_bd_pins parallella_base_0/rxo_rd_wait_p] + connect_bd_net -net parallella_base_0_rxo_wr_wait_n [get_bd_ports rxo_wr_wait_n] [get_bd_pins parallella_base_0/rxo_wr_wait_n] + connect_bd_net -net parallella_base_0_rxo_wr_wait_p [get_bd_ports rxo_wr_wait_p] [get_bd_pins parallella_base_0/rxo_wr_wait_p] + connect_bd_net -net parallella_base_0_txo_data_n [get_bd_ports txo_data_n] [get_bd_pins parallella_base_0/txo_data_n] + connect_bd_net -net parallella_base_0_txo_data_p [get_bd_ports txo_data_p] [get_bd_pins parallella_base_0/txo_data_p] + connect_bd_net -net parallella_base_0_txo_frame_n [get_bd_ports txo_frame_n] [get_bd_pins parallella_base_0/txo_frame_n] + connect_bd_net -net parallella_base_0_txo_frame_p [get_bd_ports txo_frame_p] [get_bd_pins parallella_base_0/txo_frame_p] + connect_bd_net -net parallella_base_0_txo_lclk_n [get_bd_ports txo_lclk_n] [get_bd_pins parallella_base_0/txo_lclk_n] + connect_bd_net -net parallella_base_0_txo_lclk_p [get_bd_ports txo_lclk_p] [get_bd_pins parallella_base_0/txo_lclk_p] + connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins axi_hdmi_intercon/ARESETN] [get_bd_pins axi_parallella_m_intercon/ARESETN] [get_bd_pins axi_parallella_s_intercon/ARESETN] [get_bd_pins proc_sys_reset_0/interconnect_aresetn] + connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins axi_hdmi_intercon/M00_ARESETN] [get_bd_pins axi_hdmi_intercon/M01_ARESETN] [get_bd_pins axi_hdmi_intercon/M02_ARESETN] [get_bd_pins axi_hdmi_intercon/M03_ARESETN] [get_bd_pins axi_hdmi_intercon/S00_ARESETN] [get_bd_pins axi_parallella_m_intercon/M00_ARESETN] [get_bd_pins axi_parallella_m_intercon/S00_ARESETN] [get_bd_pins axi_parallella_s_intercon/M00_ARESETN] [get_bd_pins axi_parallella_s_intercon/S00_ARESETN] [get_bd_pins hdmi_0/axi_resetn] [get_bd_pins parallella_base_0/m_axi_aresetn] [get_bd_pins parallella_base_0/s_axi_aresetn] [get_bd_pins parallella_base_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_hdmi_intercon/ACLK] [get_bd_pins axi_hdmi_intercon/M00_ACLK] [get_bd_pins axi_hdmi_intercon/M01_ACLK] [get_bd_pins axi_hdmi_intercon/M02_ACLK] [get_bd_pins axi_hdmi_intercon/M03_ACLK] [get_bd_pins axi_hdmi_intercon/S00_ACLK] [get_bd_pins axi_parallella_m_intercon/ACLK] [get_bd_pins axi_parallella_m_intercon/M00_ACLK] [get_bd_pins axi_parallella_m_intercon/S00_ACLK] [get_bd_pins axi_parallella_s_intercon/ACLK] [get_bd_pins axi_parallella_s_intercon/M00_ACLK] [get_bd_pins axi_parallella_s_intercon/S00_ACLK] [get_bd_pins hdmi_0/s_axi_aclk] [get_bd_pins parallella_base_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/DMA0_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP1_ACLK] + connect_bd_net -net processing_system7_0_FCLK_CLK2 [get_bd_pins hdmi_0/clk] [get_bd_pins processing_system7_0/FCLK_CLK2] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins proc_sys_reset_0/ext_reset_in] [get_bd_pins processing_system7_0/FCLK_RESET0_N] + connect_bd_net -net processing_system7_0_GPIO_O [get_bd_pins parallella_base_0/ps_gpio_o] [get_bd_pins processing_system7_0/GPIO_O] + connect_bd_net -net processing_system7_0_GPIO_T [get_bd_pins parallella_base_0/ps_gpio_t] [get_bd_pins processing_system7_0/GPIO_T] + connect_bd_net -net processing_system7_0_I2C0_SCL_O [get_bd_pins parallella_base_0/i2c_scl_o] [get_bd_pins processing_system7_0/I2C0_SCL_O] + connect_bd_net -net processing_system7_0_I2C0_SCL_T [get_bd_pins parallella_base_0/i2c_scl_t] [get_bd_pins processing_system7_0/I2C0_SCL_T] + connect_bd_net -net processing_system7_0_I2C0_SDA_O [get_bd_pins parallella_base_0/i2c_sda_o] [get_bd_pins processing_system7_0/I2C0_SDA_O] + connect_bd_net -net processing_system7_0_I2C0_SDA_T [get_bd_pins parallella_base_0/i2c_sda_t] [get_bd_pins processing_system7_0/I2C0_SDA_T] + connect_bd_net -net rxi_data_n_1 [get_bd_ports rxi_data_n] [get_bd_pins parallella_base_0/rxi_data_n] + connect_bd_net -net rxi_data_p_1 [get_bd_ports rxi_data_p] [get_bd_pins parallella_base_0/rxi_data_p] + connect_bd_net -net rxi_frame_n_1 [get_bd_ports rxi_frame_n] [get_bd_pins parallella_base_0/rxi_frame_n] + connect_bd_net -net rxi_frame_p_1 [get_bd_ports rxi_frame_p] [get_bd_pins parallella_base_0/rxi_frame_p] + connect_bd_net -net rxi_lclk_n_1 [get_bd_ports rxi_lclk_n] [get_bd_pins parallella_base_0/rxi_lclk_n] + connect_bd_net -net rxi_lclk_p_1 [get_bd_ports rxi_lclk_p] [get_bd_pins parallella_base_0/rxi_lclk_p] + connect_bd_net -net sys_concat_intc_dout [get_bd_pins processing_system7_0/IRQ_F2P] [get_bd_pins sys_concat_intc/dout] + connect_bd_net -net txi_rd_wait_n_1 [get_bd_ports txi_rd_wait_n] [get_bd_pins parallella_base_0/txi_rd_wait_n] + connect_bd_net -net txi_rd_wait_p_1 [get_bd_ports txi_rd_wait_p] [get_bd_pins parallella_base_0/txi_rd_wait_p] + connect_bd_net -net txi_wr_wait_n_1 [get_bd_ports txi_wr_wait_n] [get_bd_pins parallella_base_0/txi_wr_wait_n] + connect_bd_net -net txi_wr_wait_p_1 [get_bd_ports txi_wr_wait_p] [get_bd_pins parallella_base_0/txi_wr_wait_p] + + # Create address segments + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM + create_bd_addr_seg -range 0x00010000 -offset 0x66000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_clkgen_0/s_axi/axi_lite] SEG_axi_clkgen_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x6C000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_hdmi_tx_0/s_axi/axi_lite] SEG_axi_hdmi_tx_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x75C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_spdif_tx_0/s_axi/axi_lite] SEG_axi_spdif_tx_0_axi_lite + create_bd_addr_seg -range 0x00010000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_vdma_0/S_AXI_LITE/Reg] SEG_axi_vdma_0_Reg + create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_vdma_0/Data_MM2S] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/src/parallella/fpga/hdmi_e16_z7010/system_params.tcl b/src/parallella/fpga/hdmi_e16_z7010/system_params.tcl new file mode 100644 index 00000000..51b2aecf --- /dev/null +++ b/src/parallella/fpga/hdmi_e16_z7010/system_params.tcl @@ -0,0 +1,27 @@ + +#Design name ("system" recommended) +set design system + +#Project directory ("." recommended) +set projdir ./ + +#Device name +set partname "xc7z010clg400-1" + +#Paths to all IP blocks to use in Vivado "system.bd" + +set ip_repos [list "../parallella_base" "../../../adi/hdl/library"] + +#All source files +set hdl_files [] + +#All constraints files +set constraints_files [list \ + ../parallella_timing.xdc \ + ../parallella_io.xdc \ + ] + +########################################################### +# PREPARE FOR SYNTHESIS +########################################################### +set oh_verilog_define "CFG_ASIC=0 CFG_PLATFORM=\"ZYNQ\"" From 4be69a2df67d9f3bbf5009125a0882be062439fe Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 16:02:54 -0400 Subject: [PATCH 20/30] adi: hdl: Import axi_dmac IP The reference ADI design changed from using axi_vdma to axi_dmac. Import axi_dmac directory from upstream analogdevicesinc/hdl hdl_2018_R2 branch. Commit: 28df7548b002cf7201ed291a85edfa7643b5f52b --- src/adi/hdl/library/axi_dmac/2d_transfer.v | 193 +++ src/adi/hdl/library/axi_dmac/Makefile | 56 + .../hdl/library/axi_dmac/address_generator.v | 184 +++ src/adi/hdl/library/axi_dmac/axi_dmac.v | 599 +++++++++ .../library/axi_dmac/axi_dmac_burst_memory.v | 460 +++++++ .../hdl/library/axi_dmac/axi_dmac_constr.sdc | 34 + .../hdl/library/axi_dmac/axi_dmac_constr.ttcl | 250 ++++ src/adi/hdl/library/axi_dmac/axi_dmac_hw.tcl | 498 +++++++ src/adi/hdl/library/axi_dmac/axi_dmac_ip.tcl | 400 ++++++ .../hdl/library/axi_dmac/axi_dmac_pkg_sv.ttcl | 64 + .../hdl/library/axi_dmac/axi_dmac_regmap.v | 296 +++++ .../axi_dmac/axi_dmac_regmap_request.v | 308 +++++ .../library/axi_dmac/axi_dmac_reset_manager.v | 304 +++++ .../library/axi_dmac/axi_dmac_resize_dest.v | 115 ++ .../library/axi_dmac/axi_dmac_resize_src.v | 105 ++ .../axi_dmac/axi_dmac_response_manager.v | 279 ++++ .../hdl/library/axi_dmac/axi_dmac_transfer.v | 451 +++++++ .../hdl/library/axi_dmac/axi_register_slice.v | 139 ++ src/adi/hdl/library/axi_dmac/bd/bd.tcl | 161 +++ src/adi/hdl/library/axi_dmac/data_mover.v | 266 ++++ src/adi/hdl/library/axi_dmac/dest_axi_mm.v | 191 +++ .../hdl/library/axi_dmac/dest_axi_stream.v | 156 +++ src/adi/hdl/library/axi_dmac/dest_fifo_inf.v | 144 ++ src/adi/hdl/library/axi_dmac/inc_id.vh | 67 + src/adi/hdl/library/axi_dmac/request_arb.v | 1171 +++++++++++++++++ .../hdl/library/axi_dmac/request_generator.v | 255 ++++ src/adi/hdl/library/axi_dmac/resp.vh | 4 + .../hdl/library/axi_dmac/response_generator.v | 86 ++ .../hdl/library/axi_dmac/response_handler.v | 93 ++ src/adi/hdl/library/axi_dmac/splitter.v | 69 + src/adi/hdl/library/axi_dmac/src_axi_mm.v | 222 ++++ src/adi/hdl/library/axi_dmac/src_axi_stream.v | 135 ++ src/adi/hdl/library/axi_dmac/src_fifo_inf.v | 125 ++ .../hdl/library/axi_dmac/tb/axi_read_slave.v | 99 ++ src/adi/hdl/library/axi_dmac/tb/axi_slave.v | 112 ++ .../hdl/library/axi_dmac/tb/axi_write_slave.v | 130 ++ .../library/axi_dmac/tb/dma_read_shutdown_tb | 19 + .../axi_dmac/tb/dma_read_shutdown_tb.v | 162 +++ src/adi/hdl/library/axi_dmac/tb/dma_read_tb | 18 + src/adi/hdl/library/axi_dmac/tb/dma_read_tb.v | 177 +++ .../library/axi_dmac/tb/dma_write_shutdown_tb | 19 + .../axi_dmac/tb/dma_write_shutdown_tb.v | 169 +++ src/adi/hdl/library/axi_dmac/tb/dma_write_tb | 18 + .../hdl/library/axi_dmac/tb/dma_write_tb.v | 178 +++ src/adi/hdl/library/axi_dmac/tb/regmap_tb | 10 + src/adi/hdl/library/axi_dmac/tb/regmap_tb.v | 384 ++++++ .../hdl/library/axi_dmac/tb/reset_manager_tb | 8 + .../library/axi_dmac/tb/reset_manager_tb.v | 121 ++ src/adi/hdl/library/axi_dmac/tb/run_tb.sh | 24 + src/adi/hdl/library/axi_dmac/tb/tb_base.v | 76 ++ 50 files changed, 9604 insertions(+) create mode 100644 src/adi/hdl/library/axi_dmac/2d_transfer.v create mode 100644 src/adi/hdl/library/axi_dmac/Makefile create mode 100644 src/adi/hdl/library/axi_dmac/address_generator.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_burst_memory.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_constr.sdc create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_constr.ttcl create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_hw.tcl create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_ip.tcl create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_pkg_sv.ttcl create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_regmap.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_regmap_request.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_reset_manager.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_resize_dest.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_resize_src.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_response_manager.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_dmac_transfer.v create mode 100644 src/adi/hdl/library/axi_dmac/axi_register_slice.v create mode 100644 src/adi/hdl/library/axi_dmac/bd/bd.tcl create mode 100644 src/adi/hdl/library/axi_dmac/data_mover.v create mode 100644 src/adi/hdl/library/axi_dmac/dest_axi_mm.v create mode 100644 src/adi/hdl/library/axi_dmac/dest_axi_stream.v create mode 100644 src/adi/hdl/library/axi_dmac/dest_fifo_inf.v create mode 100644 src/adi/hdl/library/axi_dmac/inc_id.vh create mode 100644 src/adi/hdl/library/axi_dmac/request_arb.v create mode 100644 src/adi/hdl/library/axi_dmac/request_generator.v create mode 100644 src/adi/hdl/library/axi_dmac/resp.vh create mode 100644 src/adi/hdl/library/axi_dmac/response_generator.v create mode 100644 src/adi/hdl/library/axi_dmac/response_handler.v create mode 100644 src/adi/hdl/library/axi_dmac/splitter.v create mode 100644 src/adi/hdl/library/axi_dmac/src_axi_mm.v create mode 100644 src/adi/hdl/library/axi_dmac/src_axi_stream.v create mode 100644 src/adi/hdl/library/axi_dmac/src_fifo_inf.v create mode 100644 src/adi/hdl/library/axi_dmac/tb/axi_read_slave.v create mode 100644 src/adi/hdl/library/axi_dmac/tb/axi_slave.v create mode 100644 src/adi/hdl/library/axi_dmac/tb/axi_write_slave.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/dma_read_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/dma_read_tb.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/dma_write_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/dma_write_tb.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/regmap_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/regmap_tb.v create mode 100755 src/adi/hdl/library/axi_dmac/tb/reset_manager_tb create mode 100644 src/adi/hdl/library/axi_dmac/tb/reset_manager_tb.v create mode 100644 src/adi/hdl/library/axi_dmac/tb/run_tb.sh create mode 100644 src/adi/hdl/library/axi_dmac/tb/tb_base.v diff --git a/src/adi/hdl/library/axi_dmac/2d_transfer.v b/src/adi/hdl/library/axi_dmac/2d_transfer.v new file mode 100644 index 00000000..69ac6d0c --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/2d_transfer.v @@ -0,0 +1,193 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_2d_transfer #( + + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter BYTES_PER_BEAT_WIDTH_SRC = 3, + parameter BYTES_PER_BEAT_WIDTH_DEST = 3)( + + input req_aclk, + input req_aresetn, + + input req_valid, + output reg req_ready, + + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] req_dest_address, + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] req_src_address, + input [DMA_LENGTH_WIDTH-1:0] req_x_length, + input [DMA_LENGTH_WIDTH-1:0] req_y_length, + input [DMA_LENGTH_WIDTH-1:0] req_dest_stride, + input [DMA_LENGTH_WIDTH-1:0] req_src_stride, + input req_sync_transfer_start, + input req_last, + + output reg req_eot, + output reg [BYTES_PER_BURST_WIDTH-1:0] req_measured_burst_length, + output reg req_response_partial, + output reg req_response_valid, + input req_response_ready, + + input out_abort_req, + + output reg out_req_valid, + input out_req_ready, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] out_req_dest_address, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] out_req_src_address, + output [DMA_LENGTH_WIDTH-1:0] out_req_length, + output reg out_req_sync_transfer_start, + output out_req_last, + + input out_eot, + input [BYTES_PER_BURST_WIDTH-1:0] out_measured_burst_length, + input out_response_partial, + input out_response_valid, + output reg out_response_ready = 1'b1 + +); + +reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] dest_address = 'h00; +reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] src_address = 'h00; +reg [DMA_LENGTH_WIDTH-1:0] x_length = 'h00; +reg [DMA_LENGTH_WIDTH-1:0] y_length = 'h00; +reg [DMA_LENGTH_WIDTH-1:0] dest_stride = 'h0; +reg [DMA_LENGTH_WIDTH-1:0] src_stride = 'h00; + +reg gen_last = 'h0; + +reg [1:0] req_id = 'h00; +reg [1:0] eot_id = 'h00; +reg [3:0] last_req = 'h00; + +wire out_last; + +assign out_req_dest_address = dest_address; +assign out_req_src_address = src_address; +assign out_req_length = x_length; +assign out_last = y_length == 'h00; + +always @(posedge req_aclk) begin + if (req_aresetn == 1'b0) begin + req_id <= 2'b0; + eot_id <= 2'b0; + req_eot <= 1'b0; + end else begin + if (out_req_valid == 1'b1 && out_req_ready == 1'b1) begin + req_id <= req_id + 1'b1; + end + + if (out_eot == 1'b1 && out_response_valid == 1'b1 && out_response_ready == 1'b1) begin + eot_id <= eot_id + 1'b1; + req_eot <= last_req[eot_id]; + end else begin + req_eot <= 1'b0; + end + end +end + +always @(posedge req_aclk) begin + if (out_req_valid == 1'b1 && out_req_ready == 1'b1) begin + last_req[req_id] <= out_last; + end +end + +always @(posedge req_aclk) begin + if (out_response_valid == 1'b1 && out_response_ready == 1'b1) begin + req_measured_burst_length <= out_measured_burst_length; + req_response_partial <= out_response_partial; + end +end + +always @(posedge req_aclk) begin + if (out_response_valid == 1'b1 && out_response_ready == 1'b1) begin + req_response_valid <= 1'b1; + end else if (req_response_ready == 1'b1) begin + req_response_valid <= 1'b0; + end +end + +always @(posedge req_aclk) begin + if (req_aresetn == 1'b0) begin + out_response_ready <= 1'b1; + end else if (out_response_ready == 1'b1) begin + out_response_ready <= ~out_response_valid; + end else if (req_response_ready == 1'b1) begin + out_response_ready <= 1'b1; + end +end + +always @(posedge req_aclk) begin + if (req_ready == 1'b1 && req_valid == 1'b1) begin + dest_address <= req_dest_address; + src_address <= req_src_address; + x_length <= req_x_length; + y_length <= req_y_length; + dest_stride <= req_dest_stride; + src_stride <= req_src_stride; + out_req_sync_transfer_start <= req_sync_transfer_start; + gen_last <= req_last; + end else if (out_abort_req == 1'b1) begin + y_length <= 0; + end else if (out_req_valid == 1'b1 && out_req_ready == 1'b1) begin + dest_address <= dest_address + dest_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST]; + src_address <= src_address + src_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC]; + y_length <= y_length - 1'b1; + out_req_sync_transfer_start <= 1'b0; + end +end + +always @(posedge req_aclk) begin + if (req_aresetn == 1'b0) begin + req_ready <= 1'b1; + out_req_valid <= 1'b0; + end else begin + if (req_ready == 1'b1 && req_valid == 1'b1) begin + req_ready <= 1'b0; + out_req_valid <= 1'b1; + end else if (out_req_valid == 1'b1 && out_req_ready == 1'b1 && + out_last == 1'b1) begin + out_req_valid <= 1'b0; + req_ready <= 1'b1; + end + end +end + +assign out_req_last = out_last & gen_last; + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/Makefile b/src/adi/hdl/library/axi_dmac/Makefile new file mode 100644 index 00000000..61d74ffe --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/Makefile @@ -0,0 +1,56 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_dmac + +GENERIC_DEPS += ../common/ad_mem.v +GENERIC_DEPS += ../common/up_axi.v +GENERIC_DEPS += 2d_transfer.v +GENERIC_DEPS += address_generator.v +GENERIC_DEPS += axi_dmac.v +GENERIC_DEPS += axi_dmac_burst_memory.v +GENERIC_DEPS += axi_dmac_regmap.v +GENERIC_DEPS += axi_dmac_regmap_request.v +GENERIC_DEPS += axi_dmac_reset_manager.v +GENERIC_DEPS += axi_dmac_resize_dest.v +GENERIC_DEPS += axi_dmac_resize_src.v +GENERIC_DEPS += axi_dmac_response_manager.v +GENERIC_DEPS += axi_dmac_transfer.v +GENERIC_DEPS += axi_register_slice.v +GENERIC_DEPS += data_mover.v +GENERIC_DEPS += dest_axi_mm.v +GENERIC_DEPS += dest_axi_stream.v +GENERIC_DEPS += dest_fifo_inf.v +GENERIC_DEPS += inc_id.vh +GENERIC_DEPS += request_arb.v +GENERIC_DEPS += request_generator.v +GENERIC_DEPS += resp.vh +GENERIC_DEPS += response_generator.v +GENERIC_DEPS += response_handler.v +GENERIC_DEPS += splitter.v +GENERIC_DEPS += src_axi_mm.v +GENERIC_DEPS += src_axi_stream.v +GENERIC_DEPS += src_fifo_inf.v + +XILINX_DEPS += axi_dmac_constr.ttcl +XILINX_DEPS += axi_dmac_ip.tcl +XILINX_DEPS += bd/bd.tcl + +XILINX_DEPS += ../interfaces/fifo_rd.xml +XILINX_DEPS += ../interfaces/fifo_rd_rtl.xml +XILINX_DEPS += ../interfaces/fifo_wr.xml +XILINX_DEPS += ../interfaces/fifo_wr_rtl.xml + +XILINX_LIB_DEPS += util_axis_fifo +XILINX_LIB_DEPS += util_cdc + +ALTERA_DEPS += ../util_axis_fifo/util_axis_fifo.v +ALTERA_DEPS += ../util_axis_fifo/address_sync.v +ALTERA_DEPS += ../util_cdc/sync_bits.v +ALTERA_DEPS += ../util_cdc/sync_event.v +ALTERA_DEPS += axi_dmac_constr.sdc +ALTERA_DEPS += axi_dmac_hw.tcl + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/axi_dmac/address_generator.v b/src/adi/hdl/library/axi_dmac/address_generator.v new file mode 100644 index 00000000..49966757 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/address_generator.v @@ -0,0 +1,184 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_address_generator #( + + parameter ID_WIDTH = 3, + parameter DMA_DATA_WIDTH = 64, + parameter DMA_ADDR_WIDTH = 32, + parameter BEATS_PER_BURST_WIDTH = 4, + parameter BYTES_PER_BEAT_WIDTH = $clog2(DMA_DATA_WIDTH/8), + parameter LENGTH_WIDTH = 8)( + + input clk, + input resetn, + + input req_valid, + output reg req_ready, + input [DMA_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH] req_address, + + output reg [ID_WIDTH-1:0] id, + input [ID_WIDTH-1:0] request_id, + + input bl_valid, + output reg bl_ready, + input [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, + + input eot, + + input enable, + output reg enabled, + + input addr_ready, + output reg addr_valid, + output [DMA_ADDR_WIDTH-1:0] addr, + output [LENGTH_WIDTH-1:0] len, + output [ 2:0] size, + output [ 1:0] burst, + output [ 2:0] prot, + output [ 3:0] cache +); + +localparam MAX_BEATS_PER_BURST = {1'b1,{BEATS_PER_BURST_WIDTH{1'b0}}}; +localparam MAX_LENGTH = {BEATS_PER_BURST_WIDTH{1'b1}}; + +`include "inc_id.vh" + +assign burst = 2'b01; +assign prot = 3'b000; +assign cache = 4'b0011; +assign size = DMA_DATA_WIDTH == 1024 ? 3'b111 : + DMA_DATA_WIDTH == 512 ? 3'b110 : + DMA_DATA_WIDTH == 256 ? 3'b101 : + DMA_DATA_WIDTH == 128 ? 3'b100 : + DMA_DATA_WIDTH == 64 ? 3'b011 : + DMA_DATA_WIDTH == 32 ? 3'b010 : + DMA_DATA_WIDTH == 16 ? 3'b001 : 3'b000; + +reg [LENGTH_WIDTH-1:0] length = 'h0; +reg [DMA_ADDR_WIDTH-BYTES_PER_BEAT_WIDTH-1:0] address = 'h00; +reg [BEATS_PER_BURST_WIDTH-1:0] last_burst_len = 'h00; +assign addr = {address, {BYTES_PER_BEAT_WIDTH{1'b0}}}; +assign len = length; + +reg addr_valid_d1; +reg last = 1'b0; + +// If we already asserted addr_valid we have to wait until it is accepted before +// we can disable the address generator. +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else if (enable == 1'b1) begin + enabled <= 1'b1; + end else if (addr_valid == 1'b0) begin + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (bl_valid == 1'b1 && bl_ready == 1'b1) begin + last_burst_len <= measured_last_burst_length; + end +end + +always @(posedge clk) begin + if (addr_valid == 1'b0) begin + last <= eot; + if (eot == 1'b1) begin + length <= last_burst_len; + end else begin + length <= MAX_LENGTH; + end + end +end + +always @(posedge clk) begin + if (req_ready == 1'b1) begin + address <= req_address; + end else if (addr_valid == 1'b1 && addr_ready == 1'b1) begin + address <= address + MAX_BEATS_PER_BURST; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + bl_ready <= 1'b1; + end else begin + if (bl_ready == 1'b1) begin + bl_ready <= ~bl_valid; + end else if (addr_valid == 1'b0 && eot == 1'b1) begin + // assert bl_ready only when the addr_valid asserts in the next cycle + if (id != request_id && enable == 1'b1) begin + bl_ready <= 1'b1; + end + end + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + req_ready <= 1'b1; + addr_valid <= 1'b0; + end else begin + if (req_ready == 1'b1) begin + req_ready <= ~req_valid; + end else if (addr_valid == 1'b1 && addr_ready == 1'b1) begin + addr_valid <= 1'b0; + req_ready <= last; + end else if (id != request_id && enable == 1'b1) begin + // if eot wait until the last_burst_len gets synced over + if (eot == 1'b0 || (eot == 1'b1 && bl_ready == 1'b0)) begin + addr_valid <= 1'b1; + end + end + end +end + +always @(posedge clk) begin + addr_valid_d1 <= addr_valid; +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else if (addr_valid == 1'b1 && addr_valid_d1 == 1'b0) begin + id <= inc_id(id); + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac.v b/src/adi/hdl/library/axi_dmac/axi_dmac.v new file mode 100644 index 00000000..30e3901c --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac.v @@ -0,0 +1,599 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac #( + + parameter ID = 0, + parameter DMA_DATA_WIDTH_SRC = 64, + parameter DMA_DATA_WIDTH_DEST = 64, + parameter DMA_LENGTH_WIDTH = 24, + parameter DMA_2D_TRANSFER = 0, + parameter ASYNC_CLK_REQ_SRC = 1, + parameter ASYNC_CLK_SRC_DEST = 1, + parameter ASYNC_CLK_DEST_REQ = 1, + parameter AXI_SLICE_DEST = 0, + parameter AXI_SLICE_SRC = 0, + parameter SYNC_TRANSFER_START = 0, + parameter CYCLIC = 1, + parameter DMA_AXI_PROTOCOL_DEST = 0, + parameter DMA_AXI_PROTOCOL_SRC = 0, + parameter DMA_TYPE_DEST = 0, + parameter DMA_TYPE_SRC = 2, + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter MAX_BYTES_PER_BURST = 128, + parameter FIFO_SIZE = 8, // In bursts + parameter AXI_ID_WIDTH_SRC = 1, + parameter AXI_ID_WIDTH_DEST = 1, + parameter DISABLE_DEBUG_REGISTERS = 0, + parameter ENABLE_DIAGNOSTICS_IF = 0)( + // Slave AXI interface + input s_axi_aclk, + input s_axi_aresetn, + + input s_axi_awvalid, + input [11:0] s_axi_awaddr, + output s_axi_awready, + input [2:0] s_axi_awprot, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [11:0] s_axi_araddr, + output s_axi_arready, + input [2:0] s_axi_arprot, + output s_axi_rvalid, + input s_axi_rready, + output [ 1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + + // Interrupt + output irq, + + // Master AXI interface + input m_dest_axi_aclk, + input m_dest_axi_aresetn, + + // Write address + output [DMA_AXI_ADDR_WIDTH-1:0] m_dest_axi_awaddr, + output [7-(4*DMA_AXI_PROTOCOL_DEST):0] m_dest_axi_awlen, + output [ 2:0] m_dest_axi_awsize, + output [ 1:0] m_dest_axi_awburst, + output [ 2:0] m_dest_axi_awprot, + output [ 3:0] m_dest_axi_awcache, + output m_dest_axi_awvalid, + input m_dest_axi_awready, + output [AXI_ID_WIDTH_DEST-1:0] m_dest_axi_awid, + output [DMA_AXI_PROTOCOL_DEST:0] m_dest_axi_awlock, + + // Write data + output [DMA_DATA_WIDTH_DEST-1:0] m_dest_axi_wdata, + output [(DMA_DATA_WIDTH_DEST/8)-1:0] m_dest_axi_wstrb, + input m_dest_axi_wready, + output m_dest_axi_wvalid, + output m_dest_axi_wlast, + output [AXI_ID_WIDTH_DEST-1:0] m_dest_axi_wid, + + // Write response + input m_dest_axi_bvalid, + input [ 1:0] m_dest_axi_bresp, + output m_dest_axi_bready, + input [AXI_ID_WIDTH_DEST-1:0] m_dest_axi_bid, + + // Unused read interface + output m_dest_axi_arvalid, + output [DMA_AXI_ADDR_WIDTH-1:0] m_dest_axi_araddr, + output [7-(4*DMA_AXI_PROTOCOL_DEST):0] m_dest_axi_arlen, + output [ 2:0] m_dest_axi_arsize, + output [ 1:0] m_dest_axi_arburst, + output [ 3:0] m_dest_axi_arcache, + output [ 2:0] m_dest_axi_arprot, + input m_dest_axi_arready, + input m_dest_axi_rvalid, + input [ 1:0] m_dest_axi_rresp, + input [DMA_DATA_WIDTH_DEST-1:0] m_dest_axi_rdata, + output m_dest_axi_rready, + output [AXI_ID_WIDTH_DEST-1:0] m_dest_axi_arid, + output [DMA_AXI_PROTOCOL_DEST:0] m_dest_axi_arlock, + input [AXI_ID_WIDTH_DEST-1:0] m_dest_axi_rid, + input m_dest_axi_rlast, + + // Master AXI interface + input m_src_axi_aclk, + input m_src_axi_aresetn, + + // Read address + input m_src_axi_arready, + output m_src_axi_arvalid, + output [DMA_AXI_ADDR_WIDTH-1:0] m_src_axi_araddr, + output [7-(4*DMA_AXI_PROTOCOL_SRC):0] m_src_axi_arlen, + output [ 2:0] m_src_axi_arsize, + output [ 1:0] m_src_axi_arburst, + output [ 2:0] m_src_axi_arprot, + output [ 3:0] m_src_axi_arcache, + output [AXI_ID_WIDTH_SRC-1:0] m_src_axi_arid, + output [DMA_AXI_PROTOCOL_SRC:0] m_src_axi_arlock, + + // Read data and response + input [DMA_DATA_WIDTH_SRC-1:0] m_src_axi_rdata, + output m_src_axi_rready, + input m_src_axi_rvalid, + input [ 1:0] m_src_axi_rresp, + input [AXI_ID_WIDTH_SRC-1:0] m_src_axi_rid, + input m_src_axi_rlast, + + // Unused write interface + output m_src_axi_awvalid, + output [DMA_AXI_ADDR_WIDTH-1:0] m_src_axi_awaddr, + output [7-(4*DMA_AXI_PROTOCOL_SRC):0] m_src_axi_awlen, + output [ 2:0] m_src_axi_awsize, + output [ 1:0] m_src_axi_awburst, + output [ 3:0] m_src_axi_awcache, + output [ 2:0] m_src_axi_awprot, + input m_src_axi_awready, + output m_src_axi_wvalid, + output [DMA_DATA_WIDTH_SRC-1:0] m_src_axi_wdata, + output [(DMA_DATA_WIDTH_SRC/8)-1:0] m_src_axi_wstrb, + output m_src_axi_wlast, + input m_src_axi_wready, + input m_src_axi_bvalid, + input [ 1:0] m_src_axi_bresp, + output m_src_axi_bready, + output [AXI_ID_WIDTH_SRC-1:0] m_src_axi_awid, + output [DMA_AXI_PROTOCOL_SRC:0] m_src_axi_awlock, + output [AXI_ID_WIDTH_SRC-1:0] m_src_axi_wid, + input [AXI_ID_WIDTH_SRC-1:0] m_src_axi_bid, + + + + // Slave streaming AXI interface + input s_axis_aclk, + output s_axis_ready, + input s_axis_valid, + input [DMA_DATA_WIDTH_SRC-1:0] s_axis_data, + input [0:0] s_axis_user, + input s_axis_last, + output s_axis_xfer_req, + + // Master streaming AXI interface + input m_axis_aclk, + input m_axis_ready, + output m_axis_valid, + output [DMA_DATA_WIDTH_DEST-1:0] m_axis_data, + output m_axis_last, + output m_axis_xfer_req, + + // Input FIFO interface + input fifo_wr_clk, + input fifo_wr_en, + input [DMA_DATA_WIDTH_SRC-1:0] fifo_wr_din, + output fifo_wr_overflow, + input fifo_wr_sync, + output fifo_wr_xfer_req, + + // Input FIFO interface + input fifo_rd_clk, + input fifo_rd_en, + output fifo_rd_valid, + output [DMA_DATA_WIDTH_DEST-1:0] fifo_rd_dout, + output fifo_rd_underflow, + output fifo_rd_xfer_req, + + // Diagnostics interface + output [7:0] dest_diag_level_bursts +); + + +localparam DMA_TYPE_AXI_MM = 0; +localparam DMA_TYPE_AXI_STREAM = 1; +localparam DMA_TYPE_FIFO = 2; + +localparam HAS_DEST_ADDR = DMA_TYPE_DEST == DMA_TYPE_AXI_MM; +localparam HAS_SRC_ADDR = DMA_TYPE_SRC == DMA_TYPE_AXI_MM; + +// Argh... "[Synth 8-2722] system function call clog2 is not allowed here" +localparam BYTES_PER_BEAT_WIDTH_DEST = DMA_DATA_WIDTH_DEST > 1024 ? 8 : + DMA_DATA_WIDTH_DEST > 512 ? 7 : + DMA_DATA_WIDTH_DEST > 256 ? 6 : + DMA_DATA_WIDTH_DEST > 128 ? 5 : + DMA_DATA_WIDTH_DEST > 64 ? 4 : + DMA_DATA_WIDTH_DEST > 32 ? 3 : + DMA_DATA_WIDTH_DEST > 16 ? 2 : + DMA_DATA_WIDTH_DEST > 8 ? 1 : 0; +localparam BYTES_PER_BEAT_WIDTH_SRC = DMA_DATA_WIDTH_SRC > 1024 ? 8 : + DMA_DATA_WIDTH_SRC > 512 ? 7 : + DMA_DATA_WIDTH_SRC > 256 ? 6 : + DMA_DATA_WIDTH_SRC > 128 ? 5 : + DMA_DATA_WIDTH_SRC > 64 ? 4 : + DMA_DATA_WIDTH_SRC > 32 ? 3 : + DMA_DATA_WIDTH_SRC > 16 ? 2 : + DMA_DATA_WIDTH_SRC > 8 ? 1 : 0; +localparam ID_WIDTH = (FIFO_SIZE) > 64 ? 8 : + (FIFO_SIZE) > 32 ? 7 : + (FIFO_SIZE) > 16 ? 6 : + (FIFO_SIZE) > 8 ? 5 : + (FIFO_SIZE) > 4 ? 4 : + (FIFO_SIZE) > 2 ? 3 : + (FIFO_SIZE) > 1 ? 2 : 1; +localparam DBG_ID_PADDING = ID_WIDTH > 8 ? 0 : 8 - ID_WIDTH; + +/* AXI3 supports a maximum of 16 beats per burst. AXI4 supports a maximum of + 256 beats per burst. If either bus is AXI3 set the maximum number of beats + per burst to 16. For non AXI interfaces the maximum beats per burst is in + theory unlimted. Set it to 1024 to provide a reasonable upper threshold */ +localparam BEATS_PER_BURST_LIMIT_DEST = + (DMA_TYPE_DEST == DMA_TYPE_AXI_MM) ? + (DMA_AXI_PROTOCOL_DEST == 1 ? 16 : 256) : + 1024; +localparam BYTES_PER_BURST_LIMIT_DEST = + BEATS_PER_BURST_LIMIT_DEST * DMA_DATA_WIDTH_DEST / 8; +localparam BEATS_PER_BURST_LIMIT_SRC = + (DMA_TYPE_SRC == DMA_TYPE_AXI_MM) ? + (DMA_AXI_PROTOCOL_SRC == 1 ? 16 : 256) : + 1024; +localparam BYTES_PER_BURST_LIMIT_SRC = + BEATS_PER_BURST_LIMIT_SRC * DMA_DATA_WIDTH_SRC / 8; + +/* The smaller bus limits the maximum bytes per burst. */ +localparam BYTES_PER_BURST_LIMIT = + (BYTES_PER_BURST_LIMIT_DEST < BYTES_PER_BURST_LIMIT_SRC) ? + BYTES_PER_BURST_LIMIT_DEST : BYTES_PER_BURST_LIMIT_SRC; + +/* Make sure the requested MAX_BYTES_PER_BURST does not exceed what the + interfaces can support. Limit the value if necessary. */ +localparam REAL_MAX_BYTES_PER_BURST = + BYTES_PER_BURST_LIMIT < MAX_BYTES_PER_BURST ? + BYTES_PER_BURST_LIMIT : MAX_BYTES_PER_BURST; + +/* Align to the length to the wider interface */ +localparam DMA_LENGTH_ALIGN = + BYTES_PER_BEAT_WIDTH_DEST < BYTES_PER_BEAT_WIDTH_SRC ? + BYTES_PER_BEAT_WIDTH_SRC : BYTES_PER_BEAT_WIDTH_DEST; + +localparam BYTES_PER_BURST_WIDTH = + REAL_MAX_BYTES_PER_BURST > 2048 ? 12 : + REAL_MAX_BYTES_PER_BURST > 1024 ? 11 : + REAL_MAX_BYTES_PER_BURST > 512 ? 10 : + REAL_MAX_BYTES_PER_BURST > 256 ? 9 : + REAL_MAX_BYTES_PER_BURST > 128 ? 8 : + REAL_MAX_BYTES_PER_BURST > 64 ? 7 : + REAL_MAX_BYTES_PER_BURST > 32 ? 6 : + REAL_MAX_BYTES_PER_BURST > 16 ? 5 : + REAL_MAX_BYTES_PER_BURST > 8 ? 4 : + REAL_MAX_BYTES_PER_BURST > 4 ? 3 : + REAL_MAX_BYTES_PER_BURST > 2 ? 2 : 1; + +// ID signals from the DMAC, just for debugging +wire [ID_WIDTH-1:0] dest_request_id; +wire [ID_WIDTH-1:0] dest_data_id; +wire [ID_WIDTH-1:0] dest_address_id; +wire [ID_WIDTH-1:0] dest_response_id; +wire [ID_WIDTH-1:0] src_request_id; +wire [ID_WIDTH-1:0] src_data_id; +wire [ID_WIDTH-1:0] src_address_id; +wire [ID_WIDTH-1:0] src_response_id; +wire [11:0] dbg_status; +wire [31:0] dbg_ids0; +wire [31:0] dbg_ids1; + +assign m_dest_axi_araddr = 'd0; +assign m_dest_axi_arlen = 'd0; +assign m_dest_axi_arsize = 'd0; +assign m_dest_axi_arburst = 'd0; +assign m_dest_axi_arcache = 'd0; +assign m_dest_axi_arprot = 'd0; +assign m_dest_axi_awid = 'h0; +assign m_dest_axi_awlock = 'h0; +assign m_dest_axi_wid = 'h0; +assign m_dest_axi_arid = 'h0; +assign m_dest_axi_arlock = 'h0; +assign m_src_axi_awaddr = 'd0; +assign m_src_axi_awlen = 'd0; +assign m_src_axi_awsize = 'd0; +assign m_src_axi_awburst = 'd0; +assign m_src_axi_awcache = 'd0; +assign m_src_axi_awprot = 'd0; +assign m_src_axi_wdata = 'd0; +assign m_src_axi_wstrb = 'd0; +assign m_src_axi_wlast = 'd0; +assign m_src_axi_awid = 'h0; +assign m_src_axi_awlock = 'h0; +assign m_src_axi_wid = 'h0; +assign m_src_axi_arid = 'h0; +assign m_src_axi_arlock = 'h0; + +wire up_req_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] up_req_measured_burst_length; +wire up_response_partial; +wire up_response_valid; +wire up_response_ready; + +wire ctrl_enable; +wire ctrl_pause; + +wire up_dma_req_valid; +wire up_dma_req_ready; +wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] up_dma_req_dest_address; +wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] up_dma_req_src_address; +wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_x_length; +wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_y_length; +wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_dest_stride; +wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_src_stride; +wire up_dma_req_sync_transfer_start; +wire up_dma_req_last; + +assign dbg_ids0 = { + {DBG_ID_PADDING{1'b0}}, dest_response_id, + {DBG_ID_PADDING{1'b0}}, dest_data_id, + {DBG_ID_PADDING{1'b0}}, dest_address_id, + {DBG_ID_PADDING{1'b0}}, dest_request_id +}; + +assign dbg_ids1 = { + {DBG_ID_PADDING{1'b0}}, src_response_id, + {DBG_ID_PADDING{1'b0}}, src_data_id, + {DBG_ID_PADDING{1'b0}}, src_address_id, + {DBG_ID_PADDING{1'b0}}, src_request_id +}; + +axi_dmac_regmap #( + .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), + .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), + .DMA_CYCLIC(CYCLIC), + .HAS_DEST_ADDR(HAS_DEST_ADDR), + .HAS_SRC_ADDR(HAS_SRC_ADDR), + .DMA_2D_TRANSFER(DMA_2D_TRANSFER), + .SYNC_TRANSFER_START(SYNC_TRANSFER_START) +) i_regmap ( + .s_axi_aclk(s_axi_aclk), + .s_axi_aresetn(s_axi_aresetn), + + .s_axi_awvalid(s_axi_awvalid), + .s_axi_awaddr(s_axi_awaddr), + .s_axi_awready(s_axi_awready), + .s_axi_awprot(s_axi_awprot), + .s_axi_wvalid(s_axi_wvalid), + .s_axi_wdata(s_axi_wdata), + .s_axi_wstrb(s_axi_wstrb), + .s_axi_wready(s_axi_wready), + .s_axi_bvalid(s_axi_bvalid), + .s_axi_bresp(s_axi_bresp), + .s_axi_bready(s_axi_bready), + .s_axi_arvalid(s_axi_arvalid), + .s_axi_araddr(s_axi_araddr), + .s_axi_arready(s_axi_arready), + .s_axi_arprot(s_axi_arprot), + .s_axi_rvalid(s_axi_rvalid), + .s_axi_rready(s_axi_rready), + .s_axi_rresp(s_axi_rresp), + .s_axi_rdata(s_axi_rdata), + + // Interrupt + .irq(irq), + + // Control interface + .ctrl_enable(ctrl_enable), + .ctrl_pause(ctrl_pause), + + // Request interface + .request_valid(up_dma_req_valid), + .request_ready(up_dma_req_ready), + .request_dest_address(up_dma_req_dest_address), + .request_src_address(up_dma_req_src_address), + .request_x_length(up_dma_req_x_length), + .request_y_length(up_dma_req_y_length), + .request_dest_stride(up_dma_req_dest_stride), + .request_src_stride(up_dma_req_src_stride), + .request_sync_transfer_start(up_dma_req_sync_transfer_start), + .request_last(up_dma_req_last), + + // DMA response interface + .response_eot(up_req_eot), + .response_measured_burst_length(up_req_measured_burst_length), + .response_partial(up_response_partial), + .response_valid(up_response_valid), + .response_ready(up_response_ready), + + // Debug interface + .dbg_dest_addr(m_dest_axi_awaddr), + .dbg_src_addr(m_src_axi_araddr), + .dbg_status(dbg_status), + .dbg_ids0(dbg_ids0), + .dbg_ids1(dbg_ids1) +); + +axi_dmac_transfer #( + .DMA_DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC), + .DMA_DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .DMA_TYPE_DEST(DMA_TYPE_DEST), + .DMA_TYPE_SRC(DMA_TYPE_SRC), + .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .DMA_2D_TRANSFER(DMA_2D_TRANSFER), + .ASYNC_CLK_REQ_SRC(ASYNC_CLK_REQ_SRC), + .ASYNC_CLK_SRC_DEST(ASYNC_CLK_SRC_DEST), + .ASYNC_CLK_DEST_REQ(ASYNC_CLK_DEST_REQ), + .AXI_SLICE_DEST(AXI_SLICE_DEST), + .AXI_SLICE_SRC(AXI_SLICE_SRC), + .MAX_BYTES_PER_BURST(REAL_MAX_BYTES_PER_BURST), + .FIFO_SIZE(FIFO_SIZE), + .ID_WIDTH(ID_WIDTH), + .AXI_LENGTH_WIDTH_SRC(8-(4*DMA_AXI_PROTOCOL_SRC)), + .AXI_LENGTH_WIDTH_DEST(8-(4*DMA_AXI_PROTOCOL_DEST)), + .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF) +) i_transfer ( + .ctrl_clk(s_axi_aclk), + .ctrl_resetn(s_axi_aresetn), + + .ctrl_enable(ctrl_enable), + .ctrl_pause(ctrl_pause), + + .req_valid(up_dma_req_valid), + .req_ready(up_dma_req_ready), + .req_dest_address(up_dma_req_dest_address), + .req_src_address(up_dma_req_src_address), + .req_x_length(up_dma_req_x_length), + .req_y_length(up_dma_req_y_length), + .req_dest_stride(up_dma_req_dest_stride), + .req_src_stride(up_dma_req_src_stride), + .req_sync_transfer_start(up_dma_req_sync_transfer_start), + .req_last(up_dma_req_last), + + .req_eot(up_req_eot), + .req_measured_burst_length(up_req_measured_burst_length), + .req_response_partial(up_response_partial), + .req_response_valid(up_response_valid), + .req_response_ready(up_response_ready), + + .m_dest_axi_aclk(m_dest_axi_aclk), + .m_dest_axi_aresetn(m_dest_axi_aresetn), + .m_src_axi_aclk(m_src_axi_aclk), + .m_src_axi_aresetn(m_src_axi_aresetn), + + .m_axi_awaddr(m_dest_axi_awaddr), + .m_axi_awlen(m_dest_axi_awlen), + .m_axi_awsize(m_dest_axi_awsize), + .m_axi_awburst(m_dest_axi_awburst), + .m_axi_awprot(m_dest_axi_awprot), + .m_axi_awcache(m_dest_axi_awcache), + .m_axi_awvalid(m_dest_axi_awvalid), + .m_axi_awready(m_dest_axi_awready), + + .m_axi_wdata(m_dest_axi_wdata), + .m_axi_wstrb(m_dest_axi_wstrb), + .m_axi_wready(m_dest_axi_wready), + .m_axi_wvalid(m_dest_axi_wvalid), + .m_axi_wlast(m_dest_axi_wlast), + + .m_axi_bvalid(m_dest_axi_bvalid), + .m_axi_bresp(m_dest_axi_bresp), + .m_axi_bready(m_dest_axi_bready), + + .m_axi_arready(m_src_axi_arready), + .m_axi_arvalid(m_src_axi_arvalid), + .m_axi_araddr(m_src_axi_araddr), + .m_axi_arlen(m_src_axi_arlen), + .m_axi_arsize(m_src_axi_arsize), + .m_axi_arburst(m_src_axi_arburst), + .m_axi_arprot(m_src_axi_arprot), + .m_axi_arcache(m_src_axi_arcache), + + .m_axi_rdata(m_src_axi_rdata), + .m_axi_rready(m_src_axi_rready), + .m_axi_rvalid(m_src_axi_rvalid), + .m_axi_rlast(m_src_axi_rlast), + .m_axi_rresp(m_src_axi_rresp), + + .s_axis_aclk(s_axis_aclk), + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_data(s_axis_data), + .s_axis_user(s_axis_user), + .s_axis_last(s_axis_last), + .s_axis_xfer_req(s_axis_xfer_req), + + .m_axis_aclk(m_axis_aclk), + .m_axis_ready(m_axis_ready), + .m_axis_valid(m_axis_valid), + .m_axis_data(m_axis_data), + .m_axis_last(m_axis_last), + .m_axis_xfer_req(m_axis_xfer_req), + + .fifo_wr_clk(fifo_wr_clk), + .fifo_wr_en(fifo_wr_en), + .fifo_wr_din(fifo_wr_din), + .fifo_wr_overflow(fifo_wr_overflow), + .fifo_wr_sync(fifo_wr_sync), + .fifo_wr_xfer_req(fifo_wr_xfer_req), + + .fifo_rd_clk(fifo_rd_clk), + .fifo_rd_en(fifo_rd_en), + .fifo_rd_valid(fifo_rd_valid), + .fifo_rd_dout(fifo_rd_dout), + .fifo_rd_underflow(fifo_rd_underflow), + .fifo_rd_xfer_req(fifo_rd_xfer_req), + + // DBG + .dbg_dest_request_id(dest_request_id), + .dbg_dest_address_id(dest_address_id), + .dbg_dest_data_id(dest_data_id), + .dbg_dest_response_id(dest_response_id), + .dbg_src_request_id(src_request_id), + .dbg_src_address_id(src_address_id), + .dbg_src_data_id(src_data_id), + .dbg_src_response_id(src_response_id), + .dbg_status(dbg_status), + + .dest_diag_level_bursts(dest_diag_level_bursts) +); + +assign m_dest_axi_arvalid = 1'b0; +assign m_dest_axi_rready = 1'b0; +assign m_dest_axi_araddr = 'h0; +assign m_dest_axi_arlen = 'h0; +assign m_dest_axi_arsize = 'h0; +assign m_dest_axi_arburst = 'h0; +assign m_dest_axi_arcache = 'h0; +assign m_dest_axi_arprot = 'h0; + +assign m_src_axi_awvalid = 1'b0; +assign m_src_axi_wvalid = 1'b0; +assign m_src_axi_bready = 1'b0; +assign m_src_axi_awvalid = 'h0; +assign m_src_axi_awaddr = 'h0; +assign m_src_axi_awlen = 'h0; +assign m_src_axi_awsize = 'h0; +assign m_src_axi_awburst = 'h0; +assign m_src_axi_awcache = 'h0; +assign m_src_axi_awprot = 'h0; +assign m_src_axi_wvalid = 'h0; +assign m_src_axi_wdata = 'h0; +assign m_src_axi_wstrb = 'h0; +assign m_src_axi_wlast = 'h0; + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_burst_memory.v b/src/adi/hdl/library/axi_dmac/axi_dmac_burst_memory.v new file mode 100644 index 00000000..2addd78f --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_burst_memory.v @@ -0,0 +1,460 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_burst_memory #( + parameter DATA_WIDTH_SRC = 64, + parameter DATA_WIDTH_DEST = 64, + parameter ID_WIDTH = 3, + parameter MAX_BYTES_PER_BURST = 128, + parameter ASYNC_CLK = 1, + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DATA_WIDTH_SRC/8), + parameter BYTES_PER_BURST_WIDTH = $clog2(MAX_BYTES_PER_BURST), + parameter ENABLE_DIAGNOSTICS_IF = 0 +) ( + input src_clk, + input src_reset, + + input src_data_valid, + input [DATA_WIDTH_SRC-1:0] src_data, + input src_data_last, + input [BYTES_PER_BEAT_WIDTH_SRC-1:0] src_data_valid_bytes, + input src_data_partial_burst, + + output [ID_WIDTH-1:0] src_data_request_id, + + input dest_clk, + input dest_reset, + + output dest_data_valid, + input dest_data_ready, + output [DATA_WIDTH_DEST-1:0] dest_data, + output dest_data_last, + + output [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length, + output dest_burst_info_partial, + output [ID_WIDTH-1:0] dest_burst_info_id, + output reg dest_burst_info_write = 1'b0, + + output [ID_WIDTH-1:0] dest_request_id, + input [ID_WIDTH-1:0] dest_data_request_id, + output [ID_WIDTH-1:0] dest_data_response_id, + + // Diagnostics interface + output [7:0] dest_diag_level_bursts +); + +localparam DATA_WIDTH = DATA_WIDTH_SRC > DATA_WIDTH_DEST ? + DATA_WIDTH_SRC : DATA_WIDTH_DEST; + +/* A burst can have up to 256 beats */ +localparam BURST_LEN = MAX_BYTES_PER_BURST / (DATA_WIDTH / 8); +localparam BURST_LEN_WIDTH = BURST_LEN > 128 ? 8 : + BURST_LEN > 64 ? 7 : + BURST_LEN > 32 ? 6 : + BURST_LEN > 16 ? 5 : + BURST_LEN > 8 ? 4 : + BURST_LEN > 4 ? 3 : + BURST_LEN > 2 ? 2 : 1; + +localparam ADDRESS_WIDTH = BURST_LEN_WIDTH + ID_WIDTH - 1; + +localparam AUX_FIFO_SIZE = 2**(ID_WIDTH-1); + +localparam DEST_SRC_RATIO = DATA_WIDTH_DEST/DATA_WIDTH_SRC; + +localparam DEST_SRC_RATIO_WIDTH = DEST_SRC_RATIO > 64 ? 7 : + DEST_SRC_RATIO > 32 ? 6 : + DEST_SRC_RATIO > 16 ? 5 : + DEST_SRC_RATIO > 8 ? 4 : + DEST_SRC_RATIO > 4 ? 3 : + DEST_SRC_RATIO > 2 ? 2 : + DEST_SRC_RATIO > 1 ? 1 : 0; + +/* + * The burst memory is separated into 2**(ID_WIDTH-1) segments. Each segment can + * hold up to BURST_LEN beats. The addresses that are used to access the memory + * are split into two parts. The MSBs index the segment and the LSBs index a + * beat in a specific segment. + * + * src_id and dest_id are used to index the segment of the burst memory on the + * write and read side respectively. The IDs are 1 bit wider than the address of + * the burst memory. So we can't use them directly as an index into the burst + * memory. Since the IDs are gray counted we also can't just leave out the MSB + * like with a binary counter. But XOR-ing the two MSBs of a gray counter gives + * us a gray counter of 1 bit less. Use this to generate the segment index. + * These addresses are captured in the src_id_reduced and dest_id_reduced + * signals. + * + * src_beat_counter and dest_beat_counter are used to index the beat on the + * write and read side respectively. They will be incremented for each beat that + * is written/read. Note that the beat counters are not reset to 0 on the last + * beat of a burst. This means the first beat of a burst might not be stored at + * offset 0 in the segment memory. But this is OK since the beat counter + * increments modulo the segment size and both the write and read side agree on + * the order. + */ + +reg [ID_WIDTH-1:0] src_id_next; +reg [ID_WIDTH-1:0] src_id = 'h0; +reg src_id_reduced_msb = 1'b0; +reg [BURST_LEN_WIDTH-1:0] src_beat_counter = 'h00; + +reg [ID_WIDTH-1:0] dest_id_next = 'h0; +reg dest_id_reduced_msb_next = 1'b0; +reg dest_id_reduced_msb = 1'b0; +reg [ID_WIDTH-1:0] dest_id = 'h0; +reg [BURST_LEN_WIDTH-1:0] dest_beat_counter = 'h00; +wire [BURST_LEN_WIDTH-1:0] dest_burst_len; +reg dest_valid = 1'b0; +reg dest_mem_data_valid = 1'b0; +reg dest_mem_data_last = 1'b0; + +reg [BYTES_PER_BURST_WIDTH+1-1:0] burst_len_mem[0:AUX_FIFO_SIZE-1]; + +wire [BYTES_PER_BURST_WIDTH+1-1:0] src_burst_len_data; +reg [BYTES_PER_BURST_WIDTH+1-1:0] dest_burst_len_data = 'h00; + +wire src_beat; +wire src_last_beat; +wire [ID_WIDTH-1:0] src_dest_id; +wire [ADDRESS_WIDTH-1:0] src_waddr; +wire [ID_WIDTH-2:0] src_id_reduced; +wire src_mem_data_valid; +wire src_mem_data_last; +wire [DATA_WIDTH-1:0] src_mem_data; + +wire dest_beat; +wire dest_last_beat; +wire dest_last; +wire [ID_WIDTH-1:0] dest_src_id; +wire [ADDRESS_WIDTH-1:0] dest_raddr; +wire [ID_WIDTH-2:0] dest_id_reduced_next; +wire [ID_WIDTH-1:0] dest_id_next_inc; +wire [ID_WIDTH-2:0] dest_id_reduced; +wire dest_burst_valid; +wire dest_burst_ready; +wire dest_ready; +wire [DATA_WIDTH-1:0] dest_mem_data; +wire dest_mem_data_ready; + +`include "inc_id.vh" + +generate if (ID_WIDTH >= 3) begin + assign src_id_reduced = {src_id_reduced_msb,src_id[ID_WIDTH-3:0]}; + assign dest_id_reduced_next = {dest_id_reduced_msb_next,dest_id_next[ID_WIDTH-3:0]}; + assign dest_id_reduced = {dest_id_reduced_msb,dest_id[ID_WIDTH-3:0]}; +end else begin + assign src_id_reduced = src_id_reduced_msb; + assign dest_id_reduced_next = dest_id_reduced_msb_next; + assign dest_id_reduced = dest_id_reduced_msb; +end endgenerate + +assign src_beat = src_mem_data_valid; +assign src_last_beat = src_beat & src_mem_data_last; +assign src_waddr = {src_id_reduced,src_beat_counter}; + +assign src_data_request_id = src_dest_id; + +always @(*) begin + if (src_last_beat == 1'b1) begin + src_id_next <= inc_id(src_id); + end else begin + src_id_next <= src_id; + end +end + +always @(posedge src_clk) begin + if (src_reset == 1'b1) begin + src_id <= 'h00; + src_id_reduced_msb <= 1'b0; + end else begin + src_id <= src_id_next; + src_id_reduced_msb <= ^src_id_next[ID_WIDTH-1-:2]; + end +end + +always @(posedge src_clk) begin + if (src_reset == 1'b1) begin + src_beat_counter <= 'h00; + end else if (src_beat == 1'b1) begin + src_beat_counter <= src_beat_counter + 1'b1; + end +end + +always @(posedge src_clk) begin + if (src_last_beat == 1'b1) begin + burst_len_mem[src_id_reduced] <= src_burst_len_data; + end +end + +assign dest_ready = ~dest_mem_data_valid | dest_mem_data_ready; +assign dest_last = dest_beat_counter == dest_burst_len; + +assign dest_beat = dest_valid & dest_ready; +assign dest_last_beat = dest_last & dest_beat; +assign dest_raddr = {dest_id_reduced,dest_beat_counter}; + +assign dest_burst_valid = dest_data_request_id != dest_id_next; +assign dest_burst_ready = ~dest_valid | dest_last_beat; + +/* + * The data valid signal for the destination side is asserted if there are one + * or more pending bursts. It is de-asserted if there are no more pending burst + * and it is the last beat of the current burst + */ +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_valid <= 1'b0; + end else if (dest_burst_valid == 1'b1) begin + dest_valid <= 1'b1; + end else if (dest_last_beat == 1'b1) begin + dest_valid <= 1'b0; + end +end + +/* + * The output register of the memory creates a extra clock cycle of latency on + * the data path. We need to handle this more the handshaking signals. If data + * is available in the memory it will be available one clock cycle later in the + * output register. + */ +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_mem_data_valid <= 1'b0; + end else if (dest_valid == 1'b1) begin + dest_mem_data_valid <= 1'b1; + end else if (dest_mem_data_ready == 1'b1) begin + dest_mem_data_valid <= 1'b0; + end +end + +/* + * This clears dest_data_last after the last beat. Strictly speaking this is not + * necessary if this followed AXI handshaking rules since dest_data_last would + * be qualified by dest_data_valid and it is OK to retain the previous value of + * dest_data_last when dest_data_valid is not asserted. But clearing the signal + * here doesn't cost much and can simplify some of the more congested + * combinatorical logic further up the pipeline since we can assume that + * fifo_last == 1'b1 implies fifo_valid == 1'b1. + */ +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_mem_data_last <= 1'b0; + end else if (dest_beat == 1'b1) begin + dest_mem_data_last <= dest_last; + end else if (dest_mem_data_ready == 1'b1) begin + dest_mem_data_last <= 1'b0; + end +end + +assign dest_id_next_inc = inc_id(dest_id_next); + +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_id_next <= 'h00; + dest_id_reduced_msb_next <= 1'b0; + end else if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) begin + dest_id_next <= dest_id_next_inc; + dest_id_reduced_msb_next <= ^dest_id_next_inc[ID_WIDTH-1-:2]; + end +end + +always @(posedge dest_clk) begin + if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) begin + dest_burst_len_data <= burst_len_mem[dest_id_reduced_next]; + end +end + +always @(posedge dest_clk) begin + if (dest_burst_ready == 1'b1) begin + dest_id <= dest_id_next; + dest_id_reduced_msb <= dest_id_reduced_msb_next; + end +end + +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_beat_counter <= 'h00; + end else if (dest_beat == 1'b1) begin + dest_beat_counter <= dest_beat_counter + 1'b1; + end +end + +assign dest_burst_info_length = dest_burst_len_data[BYTES_PER_BURST_WIDTH-1:0]; +assign dest_burst_info_partial = dest_burst_len_data[BYTES_PER_BURST_WIDTH]; +assign dest_burst_info_id = dest_id; + +always @(posedge dest_clk) begin + dest_burst_info_write <= (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1); +end + +// If destination is wider track the number of source beats in a destination +// beat in case the stream is not destination width aligned. +generate if (DATA_WIDTH_SRC < DATA_WIDTH_DEST) begin + + reg [DEST_SRC_RATIO_WIDTH-1:0] src_num_beats = {DEST_SRC_RATIO_WIDTH{1'b1}}; + reg [BYTES_PER_BEAT_WIDTH_SRC-1:0] src_data_valid_bytes_d = 'h00; + reg src_data_partial_burst_d = 'h0; + + // This counter will hold the number of source beat in a destination beat + // minus one + always @(posedge src_clk) begin + if (src_mem_data_last == 1'b1 && src_mem_data_valid == 1'b1) begin + if (src_data_valid) begin + src_num_beats <= {DEST_SRC_RATIO_WIDTH{1'b0}}; + end else begin + src_num_beats <= {DEST_SRC_RATIO_WIDTH{1'b1}}; + end + end else if (src_data_valid) begin + src_num_beats <= src_num_beats + 1'b1; + end + end + + // Compensate the delay through the resize block + always @(posedge src_clk) begin + if (src_data_valid == 1'b1) begin + src_data_valid_bytes_d <= src_data_valid_bytes; + src_data_partial_burst_d <= src_data_partial_burst; + end + end + + assign src_burst_len_data = {src_data_partial_burst_d, + src_beat_counter, + src_num_beats, + src_data_valid_bytes_d}; +end else begin + + assign src_burst_len_data = {src_data_partial_burst, + src_beat_counter, + src_data_valid_bytes}; +end +endgenerate + +assign dest_burst_len = dest_burst_len_data[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH]; + +axi_dmac_resize_src #( + .DATA_WIDTH_SRC (DATA_WIDTH_SRC), + .DATA_WIDTH_MEM (DATA_WIDTH) +) i_resize_src ( + .clk (src_clk), + .reset (src_reset), + + .src_data_valid (src_data_valid), + .src_data (src_data), + .src_data_last (src_data_last), + + .mem_data_valid (src_mem_data_valid), + .mem_data (src_mem_data), + .mem_data_last (src_mem_data_last) +); + +ad_mem #( + .DATA_WIDTH (DATA_WIDTH), + .ADDRESS_WIDTH (ADDRESS_WIDTH) +) i_mem ( + .clka (src_clk), + .wea (src_beat), + .addra (src_waddr), + .dina (src_mem_data), + + .clkb (dest_clk), + .reb (dest_beat), + .addrb (dest_raddr), + .doutb (dest_mem_data) +); + +axi_dmac_resize_dest #( + .DATA_WIDTH_DEST (DATA_WIDTH_DEST), + .DATA_WIDTH_MEM (DATA_WIDTH) +) i_resize_dest ( + .clk (dest_clk), + .reset (dest_reset), + + .mem_data_valid (dest_mem_data_valid), + .mem_data_ready (dest_mem_data_ready), + .mem_data (dest_mem_data), + .mem_data_last (dest_mem_data_last), + + .dest_data_valid (dest_data_valid), + .dest_data_ready (dest_data_ready), + .dest_data (dest_data), + .dest_data_last (dest_data_last) +); + +sync_bits #( + .NUM_OF_BITS (ID_WIDTH), + .ASYNC_CLK (ASYNC_CLK) +) i_dest_sync_id ( + .in (src_id), + .out_clk (dest_clk), + .out_resetn (1'b1), + .out (dest_src_id) +); + +sync_bits #( + .NUM_OF_BITS (ID_WIDTH), + .ASYNC_CLK (ASYNC_CLK) +) i_src_sync_id ( + .in (dest_id), + .out_clk (src_clk), + .out_resetn (1'b1), + .out (src_dest_id) +); + +assign dest_request_id = dest_src_id; +assign dest_data_response_id = dest_id; + +generate if (ENABLE_DIAGNOSTICS_IF == 1) begin + + reg [ID_WIDTH-1:0] _dest_diag_level_bursts = 'h0; + + // calculate buffer fullness in bursts + always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + _dest_diag_level_bursts <= 'h0; + end else begin + _dest_diag_level_bursts <= g2b(dest_src_id) - g2b(dest_id); + end + end + assign dest_diag_level_bursts = {{{8-ID_WIDTH}{1'b0}},_dest_diag_level_bursts}; + +end else begin + assign dest_diag_level_bursts = 'h0; +end +endgenerate + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_constr.sdc b/src/adi/hdl/library/axi_dmac/axi_dmac_constr.sdc new file mode 100644 index 00000000..2e482979 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_constr.sdc @@ -0,0 +1,34 @@ + + +set_false_path -to [get_registers *axi_dmac*cdc_sync_stage1*] +set_false_path -from [get_registers *axi_dmac*cdc_sync_fifo_ram*] +set_false_path -from [get_registers *axi_dmac*eot_mem*] +set_false_path -from [get_registers *axi_dmac*bl_mem*] + +# Burst memory +set_false_path -from [get_registers *axi_dmac*burst_len_mem*] + +# Reset manager +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|do_reset}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[*]|clrn}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[0]}] \ + -to [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[3]}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[0]}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync_in|clrn}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync[0]}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync_in|clrn}] + +# Debug signals +set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|cdc_sync_stage2*] -to [get_registers *axi_dmac*up_rdata*] +set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|*id*] -to [get_registers *axi_dmac*up_rdata*] +set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|address*] -to [get_registers *axi_dmac*up_rdata*] +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync[0]}] \ + -to [get_registers {*|axi_dmac_regmap:i_regmap|up_rdata[*]}] diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_constr.ttcl b/src/adi/hdl/library/axi_dmac/axi_dmac_constr.ttcl new file mode 100644 index 00000000..f947fe18 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_constr.ttcl @@ -0,0 +1,250 @@ +<: set ComponentName [getComponentNameString] :> +<: setOutputDirectory "./" :> +<: setFileName [ttcl_add $ComponentName "_constr"] :> +<: setFileExtension ".xdc" :> +<: setFileProcessingOrder late :> +<: set async_dest_req [getBooleanValue "ASYNC_CLK_DEST_REQ"] :> +<: set async_req_src [getBooleanValue "ASYNC_CLK_REQ_SRC"] :> +<: set async_src_dest [getBooleanValue "ASYNC_CLK_SRC_DEST"] :> +<: set disable_debug_registers [getBooleanValue "DISABLE_DEBUG_REGISTERS"] :> + +set req_clk [get_clocks -of_objects [get_ports s_axi_aclk]] +set src_clk [get_clocks -of_objects [get_ports -quiet {fifo_wr_clk s_axis_aclk m_src_axi_aclk}]] +set dest_clk [get_clocks -of_objects [get_ports -quiet {fifo_rd_clk m_axis_aclk m_dest_axi_aclk}]] + +<: if {$async_req_src || $async_src_dest || $async_dest_req} { :> +set_property ASYNC_REG TRUE \ + [get_cells -quiet -hier *cdc_sync_stage1_reg*] \ + [get_cells -quiet -hier *cdc_sync_stage2_reg*] + +<: } :> +<: if {$async_req_src} { :> +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_src_request_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $req_clk] + +set_false_path -quiet \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_status_src* && IS_SEQUENTIAL}] + +set_false_path -quiet \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_control_src* && IS_SEQUENTIAL}] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_req_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $req_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_req_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_src_req_fifo* && IS_SEQUENTIAL}] \ + -to $src_clk \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -through [get_cells -quiet -hier DP \ + -filter {NAME =~ *i_request_arb/eot_mem_src_reg*}] \ + -to $src_clk \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_rewind_req_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_rewind_req_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_rewind_req_fifo* && IS_SEQUENTIAL}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +set_false_path -quiet \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *sync_rewind/i_sync_out* && IS_SEQUENTIAL}] + +set_false_path -quiet \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *sync_rewind/i_sync_in* && IS_SEQUENTIAL}] + +<: } :> +<: if {$async_dest_req} { :> +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_req_response_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_false_path -quiet \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_status_dest* && IS_SEQUENTIAL}] + +set_false_path -quiet \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_control_dest* && IS_SEQUENTIAL}] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_response_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_response_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $req_clk] +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_dest_response_fifo* && IS_SEQUENTIAL}] \ + -to $req_clk \ + [get_property -min PERIOD $req_clk] + +<: } :> +<: if {$async_src_dest} { :> +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_dest_request_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_store_and_forward/i_dest_sync_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_store_and_forward/i_src_sync_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -through [get_cells -quiet -hier \ + -filter {IS_SEQUENTIAL && NAME =~ *i_store_and_forward/burst_len_mem_reg*}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_req_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_req_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_dest_req_fifo* && IS_SEQUENTIAL}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_dest_bl_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_dest_bl_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_src_dest_bl_fifo* && IS_SEQUENTIAL}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + + set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -through [get_cells -quiet -hier DP \ + -filter {NAME =~ *i_request_arb/eot_mem_dest_reg*}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +<: } :> +# Reset signals +set_false_path -quiet \ + -from [get_cells -quiet -hier *do_reset_reg* \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_async_reg*/PRE] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_async_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *reset_async_reg[3]* \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_async_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_sync_in_reg*/PRE \ + -filter {NAME =~ *i_reset_manager*}] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_sync_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_sync_in_reg*/PRE \ + -filter {NAME =~ *i_reset_manager*}] + +set_property -dict { \ + SHREG_EXTRACT NO \ + ASYNC_REG TRUE \ + } [get_cells -quiet -hier *reset_async_reg*] + +set_property -dict { \ + SHREG_EXTRACT NO \ + ASYNC_REG TRUE \ + } [get_cells -quiet -hier *reset_sync_reg*] + +# Ignore timing for debug signals to register map +<: if {!$disable_debug_registers} { :> +set_false_path -quiet \ + -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ + -filter {name =~ *i_sync_src_request_id* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ + -filter {name =~ *i_dest_sync_id* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *id_reg* -filter {name =~ *i_request_arb* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *address_reg* -filter {name =~ *i_addr_gen* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_sync_reg* -filter {name =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +<: } :> diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_hw.tcl b/src/adi/hdl/library/axi_dmac/axi_dmac_hw.tcl new file mode 100644 index 00000000..933a850d --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_hw.tcl @@ -0,0 +1,498 @@ + + +package require qsys +source ../scripts/adi_env.tcl +source ../scripts/adi_ip_alt.tcl + +set_module_property NAME axi_dmac +set_module_property DESCRIPTION "AXI DMA Controller" +set_module_property VERSION 1.0 +set_module_property GROUP "Analog Devices" +set_module_property DISPLAY_NAME axi_dmac +set_module_property ELABORATION_CALLBACK axi_dmac_elaborate +set_module_property VALIDATION_CALLBACK axi_dmac_validate + +# files + +ad_ip_files axi_dmac [list \ + $ad_hdl_dir/library/util_cdc/sync_bits.v \ + $ad_hdl_dir/library/util_cdc/sync_event.v \ + $ad_hdl_dir/library/common/up_axi.v \ + $ad_hdl_dir/library/util_axis_fifo/util_axis_fifo.v \ + $ad_hdl_dir/library/util_axis_fifo/address_sync.v \ + $ad_hdl_dir/library/common/ad_mem.v \ + inc_id.vh \ + resp.vh \ + axi_dmac_burst_memory.v \ + axi_dmac_regmap.v \ + axi_dmac_regmap_request.v \ + axi_dmac_reset_manager.v \ + axi_dmac_resize_dest.v \ + axi_dmac_resize_src.v \ + axi_dmac_response_manager.v \ + axi_dmac_transfer.v \ + address_generator.v \ + data_mover.v \ + request_arb.v \ + request_generator.v \ + response_handler.v \ + axi_register_slice.v \ + 2d_transfer.v \ + dest_axi_mm.v \ + dest_axi_stream.v \ + dest_fifo_inf.v \ + src_axi_mm.v \ + src_axi_stream.v \ + src_fifo_inf.v \ + splitter.v \ + response_generator.v \ + axi_dmac.v \ + axi_dmac_constr.sdc \ +] + +# Disable dual-clock RAM read-during-write behaviour warning. +set_qip_strings { "set_instance_assignment -name MESSAGE_DISABLE 276027 -entity axi_dmac_burst_memory" } + +# parameters + +set group "General Configuration" + +add_parameter ID INTEGER 0 +set_parameter_property ID DISPLAY_NAME "Core ID" +set_parameter_property ID HDL_PARAMETER true +set_parameter_property ID GROUP $group + +add_parameter DMA_LENGTH_WIDTH INTEGER 24 +set_parameter_property DMA_LENGTH_WIDTH DISPLAY_NAME "DMA Transfer Length Register Width" +set_parameter_property DMA_LENGTH_WIDTH UNITS Bits +set_parameter_property DMA_LENGTH_WIDTH HDL_PARAMETER true +set_parameter_property DMA_LENGTH_WIDTH ALLOWED_RANGES {8:32} +set_parameter_property DMA_LENGTH_WIDTH GROUP $group + +add_parameter FIFO_SIZE INTEGER 8 +set_parameter_property FIFO_SIZE DISPLAY_NAME "Store-and-Forward Memory Size (In Bursts)" +set_parameter_property FIFO_SIZE HDL_PARAMETER true +set_parameter_property FIFO_SIZE ALLOWED_RANGES {2 4 8 16 32} +set_parameter_property FIFO_SIZE GROUP $group + +add_parameter MAX_BYTES_PER_BURST INTEGER 128 +set_parameter_property MAX_BYTES_PER_BURST DISPLAY_NAME "Maximum bytes per burst" +set_parameter_property MAX_BYTES_PER_BURST HDL_PARAMETER true +set_parameter_property MAX_BYTES_PER_BURST GROUP $group + +foreach {suffix group} { \ + "SRC" "Source" \ + "DEST" "Destination" \ + } { + + add_display_item "Endpoint Configuration" $group "group" + + add_parameter DMA_TYPE_$suffix INTEGER 0 + set_parameter_property DMA_TYPE_$suffix DISPLAY_NAME "Type" + set_parameter_property DMA_TYPE_$suffix HDL_PARAMETER true + set_parameter_property DMA_TYPE_$suffix ALLOWED_RANGES \ + { "0:Memory-Mapped AXI" "1:Streaming AXI" "2:FIFO Interface" } + set_parameter_property DMA_TYPE_$suffix GROUP $group + + add_parameter DMA_AXI_PROTOCOL_$suffix INTEGER 1 + set_parameter_property DMA_AXI_PROTOCOL_$suffix DISPLAY_NAME "AXI Protocol" + set_parameter_property DMA_AXI_PROTOCOL_$suffix HDL_PARAMETER true + set_parameter_property DMA_AXI_PROTOCOL_$suffix ALLOWED_RANGES { "0:AXI4" "1:AXI3" } + set_parameter_property DMA_AXI_PROTOCOL_$suffix GROUP $group + + add_parameter DMA_DATA_WIDTH_$suffix INTEGER 64 + set_parameter_property DMA_DATA_WIDTH_$suffix DISPLAY_NAME "Bus Width" + set_parameter_property DMA_DATA_WIDTH_$suffix UNITS Bits + set_parameter_property DMA_DATA_WIDTH_$suffix HDL_PARAMETER true + set_parameter_property DMA_DATA_WIDTH_$suffix ALLOWED_RANGES {16 32 64 128 256 512 1024} + set_parameter_property DMA_DATA_WIDTH_$suffix GROUP $group + + add_parameter USE_TLAST_$suffix INTEGER 0 + set_parameter_property USE_TLAST_$suffix DISPLAY_NAME "Use TLAST" + set_parameter_property USE_TLAST_$suffix HDL_PARAMETER false + set_parameter_property USE_TLAST_$suffix DISPLAY_HINT boolean + set_parameter_property USE_TLAST_$suffix GROUP $group + + add_parameter AXI_SLICE_$suffix INTEGER 0 + set_parameter_property AXI_SLICE_$suffix DISPLAY_NAME "Insert Register Slice" + set_parameter_property AXI_SLICE_$suffix DISPLAY_HINT boolean + set_parameter_property AXI_SLICE_$suffix HDL_PARAMETER true + set_parameter_property AXI_SLICE_$suffix GROUP $group +} + +# FIFO interface +set_parameter_property DMA_TYPE_SRC DEFAULT_VALUE 2 + +set group "Features" + +add_parameter CYCLIC INTEGER 1 +set_parameter_property CYCLIC DISPLAY_NAME "Cyclic Transfer Support" +set_parameter_property CYCLIC DISPLAY_HINT boolean +set_parameter_property CYCLIC HDL_PARAMETER true +set_parameter_property CYCLIC GROUP $group + +add_parameter DMA_2D_TRANSFER INTEGER 0 +set_parameter_property DMA_2D_TRANSFER DISPLAY_NAME "2D Transfer Support" +set_parameter_property DMA_2D_TRANSFER DISPLAY_HINT boolean +set_parameter_property DMA_2D_TRANSFER HDL_PARAMETER true +set_parameter_property DMA_2D_TRANSFER GROUP $group + +add_parameter SYNC_TRANSFER_START INTEGER 0 +set_parameter_property SYNC_TRANSFER_START DISPLAY_NAME "Transfer Start Synchronization Support" +set_parameter_property SYNC_TRANSFER_START DISPLAY_HINT boolean +set_parameter_property SYNC_TRANSFER_START HDL_PARAMETER true +set_parameter_property SYNC_TRANSFER_START GROUP $group + +set group "Clock Domain Configuration" + +add_parameter AUTO_ASYNC_CLK BOOLEAN 1 +set_parameter_property AUTO_ASYNC_CLK DISPLAY_NAME "Automatically Detect Clock Domains" +set_parameter_property AUTO_ASYNC_CLK HDL_PARAMETER false +set_parameter_property AUTO_ASYNC_CLK GROUP $group + +foreach {p name} { \ + ASYNC_CLK_REQ_SRC "Request and Source" \ + ASYNC_CLK_SRC_DEST "Source and Destination" \ + ASYNC_CLK_DEST_REQ "Destination and Request" \ + } { + + add_parameter ${p}_MANUAL INTEGER 1 + set_parameter_property ${p}_MANUAL DISPLAY_NAME [concat $name "Clock Asynchronous"] + set_parameter_property ${p}_MANUAL DISPLAY_HINT boolean + set_parameter_property ${p}_MANUAL HDL_PARAMETER false + set_parameter_property ${p}_MANUAL VISIBLE false + set_parameter_property ${p}_MANUAL GROUP $group + + add_parameter $p INTEGER 1 + set_parameter_property $p DISPLAY_NAME [concat $name "Clock Asynchronous"] + set_parameter_property $p DISPLAY_HINT boolean + set_parameter_property $p HDL_PARAMETER true + set_parameter_property $p DERIVED true + set_parameter_property $p GROUP $group +} + +add_parameter CLK_DOMAIN_REQ INTEGER +set_parameter_property CLK_DOMAIN_REQ HDL_PARAMETER false +set_parameter_property CLK_DOMAIN_REQ SYSTEM_INFO {CLOCK_DOMAIN s_axi_clock} +set_parameter_property CLK_DOMAIN_REQ VISIBLE false +set_parameter_property CLK_DOMAIN_REQ GROUP $group + +set src_clks { \ + {CLK_DOMAIN_SRC_AXI m_src_axi_clock} \ + {CLK_DOMAIN_SRC_SAXI if_s_axis_aclk} \ + {CLK_DOMAIN_SRC_FIFO if_fifo_wr_clk} \ +} + +set dest_clks { \ + {CLK_DOMAIN_DEST_AXI m_dest_axi_clock} \ + {CLK_DOMAIN_DEST_SAXI if_m_axis_aclk} \ + {CLK_DOMAIN_DEST_FIFO if_fifo_rd_clk} \ +} + +foreach domain [list {*}$src_clks {*}$dest_clks] { + lassign $domain p clk + add_parameter $p INTEGER + set_parameter_property $p HDL_PARAMETER false + set_parameter_property $p SYSTEM_INFO [list CLOCK_DOMAIN $clk] + set_parameter_property $p VISIBLE false + set_parameter_property $p GROUP $group +} + +# axi4 slave + +ad_ip_intf_s_axi s_axi_aclk s_axi_aresetn 12 + +add_interface interrupt_sender interrupt end +set_interface_property interrupt_sender associatedAddressablePoint s_axi +set_interface_property interrupt_sender associatedClock s_axi_clock +set_interface_property interrupt_sender associatedReset s_axi_reset +set_interface_property interrupt_sender ENABLED true +set_interface_property interrupt_sender EXPORT_OF "" +set_interface_property interrupt_sender PORT_NAME_MAP "" +set_interface_property interrupt_sender CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_sender SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_sender irq irq Output 1 + +proc axi_dmac_validate {} { + set auto_clk [get_parameter_value AUTO_ASYNC_CLK] + set type_src [get_parameter_value DMA_TYPE_SRC] + set type_dest [get_parameter_value DMA_TYPE_DEST] + + set max_burst 32768 + + if {$auto_clk == true} { + global src_clks dest_clks + + set req_domain [get_parameter_value CLK_DOMAIN_REQ] + set src_domain [get_parameter_value [lindex $src_clks $type_src 0]] + set dest_domain [get_parameter_value [lindex $dest_clks $type_dest 0]] + + if {$req_domain != 0 && $req_domain == $src_domain} { + set_parameter_value ASYNC_CLK_REQ_SRC 0 + } else { + set_parameter_value ASYNC_CLK_REQ_SRC 1 + } + + if {$src_domain != 0 && $src_domain == $dest_domain} { + set_parameter_value ASYNC_CLK_SRC_DEST 0 + } else { + set_parameter_value ASYNC_CLK_SRC_DEST 1 + } + + if {$dest_domain != 0 && $dest_domain == $req_domain} { + set_parameter_value ASYNC_CLK_DEST_REQ 0 + } else { + set_parameter_value ASYNC_CLK_DEST_REQ 1 + } + } else { + foreach p {ASYNC_CLK_REQ_SRC ASYNC_CLK_SRC_DEST ASYNC_CLK_DEST_REQ} { + set_parameter_value $p [get_parameter_value ${p}_MANUAL] + } + } + + foreach p {ASYNC_CLK_REQ_SRC ASYNC_CLK_SRC_DEST ASYNC_CLK_DEST_REQ} { + set_parameter_property ${p}_MANUAL VISIBLE [expr $auto_clk ? false : true] + set_parameter_property $p VISIBLE $auto_clk + } + foreach suffix {SRC DEST} { + if {[get_parameter_value DMA_TYPE_$suffix] == 0} { + set show_axi_protocol true + set proto [get_parameter_value DMA_AXI_PROTOCOL_$suffix] + set width [get_parameter_value DMA_DATA_WIDTH_$suffix] + if {$proto == 0} { + set max_burst [expr min($max_burst, $width * 256 / 8)] + } else { + set max_burst [expr min($max_burst, $width * 16 / 8)] + } + } else { + set show_axi_protocol false + } + set_parameter_property DMA_AXI_PROTOCOL_$suffix VISIBLE $show_axi_protocol + } + + foreach suffix {SRC DEST} { + if {[get_parameter_value DMA_TYPE_$suffix] == 1} { + set_parameter_property USE_TLAST_$suffix VISIBLE true + } else { + set_parameter_property USE_TLAST_$suffix VISIBLE false + } + } + set_parameter_property MAX_BYTES_PER_BURST ALLOWED_RANGES "1:$max_burst" +} + +# conditional interfaces + +# axi4 destination/source + +add_interface m_dest_axi_clock clock end +add_interface_port m_dest_axi_clock m_dest_axi_aclk clk Input 1 + +add_interface m_dest_axi_reset reset end +set_interface_property m_dest_axi_reset associatedClock m_dest_axi_clock +add_interface_port m_dest_axi_reset m_dest_axi_aresetn reset_n Input 1 + + +add_interface m_src_axi_clock clock end +add_interface_port m_src_axi_clock m_src_axi_aclk clk Input 1 + +add_interface m_src_axi_reset reset end +set_interface_property m_src_axi_reset associatedClock m_src_axi_clock +add_interface_port m_src_axi_reset m_src_axi_aresetn reset_n Input 1 + +# axis destination/source + +ad_alt_intf clock m_axis_aclk input 1 clk +ad_alt_intf signal m_axis_valid output 1 valid +ad_alt_intf signal m_axis_data output DMA_DATA_WIDTH_DEST data +ad_alt_intf signal m_axis_ready input 1 ready +ad_alt_intf signal m_axis_last output 1 last +ad_alt_intf signal m_axis_xfer_req output 1 xfer_req + +ad_alt_intf clock s_axis_aclk input 1 clk +ad_alt_intf signal s_axis_valid input 1 valid +ad_alt_intf signal s_axis_data input DMA_DATA_WIDTH_SRC data +ad_alt_intf signal s_axis_ready output 1 ready +ad_alt_intf signal s_axis_last input 1 last +ad_alt_intf signal s_axis_xfer_req output 1 xfer_req +ad_alt_intf signal s_axis_user input 1 user + +# fifo destination/source + +ad_alt_intf clock fifo_rd_clk input 1 clk +ad_alt_intf signal fifo_rd_en input 1 valid +ad_alt_intf signal fifo_rd_valid output 1 valid +ad_alt_intf signal fifo_rd_dout output DMA_DATA_WIDTH_DEST data +ad_alt_intf signal fifo_rd_underflow output 1 unf +ad_alt_intf signal fifo_rd_xfer_req output 1 xfer_req + +ad_alt_intf clock fifo_wr_clk input 1 clk +ad_alt_intf signal fifo_wr_en input 1 valid +ad_alt_intf signal fifo_wr_din input DMA_DATA_WIDTH_SRC data +ad_alt_intf signal fifo_wr_overflow output 1 ovf +ad_alt_intf signal fifo_wr_sync input 1 sync +ad_alt_intf signal fifo_wr_xfer_req output 1 xfer_req + +proc add_axi_master_interface {axi_type port suffix} { + add_interface $port $axi_type start + set_interface_property $port associatedClock ${port}_clock + set_interface_property $port associatedReset ${port}_reset + set_interface_property $port readIssuingCapability 1 + add_interface_port $port ${port}_awvalid awvalid Output 1 + add_interface_port $port ${port}_awaddr awaddr Output 32 + add_interface_port $port ${port}_awready awready Input 1 + add_interface_port $port ${port}_wvalid wvalid Output 1 + add_interface_port $port ${port}_wdata wdata Output DMA_DATA_WIDTH_${suffix} + add_interface_port $port ${port}_wstrb wstrb Output DMA_DATA_WIDTH_${suffix}/8 + add_interface_port $port ${port}_wready wready Input 1 + add_interface_port $port ${port}_bvalid bvalid Input 1 + add_interface_port $port ${port}_bresp bresp Input 2 + add_interface_port $port ${port}_bready bready Output 1 + add_interface_port $port ${port}_arvalid arvalid Output 1 + add_interface_port $port ${port}_araddr araddr Output 32 + add_interface_port $port ${port}_arready arready Input 1 + add_interface_port $port ${port}_rvalid rvalid Input 1 + add_interface_port $port ${port}_rresp rresp Input 2 + add_interface_port $port ${port}_rdata rdata Input DMA_DATA_WIDTH_${suffix} + add_interface_port $port ${port}_rready rready Output 1 + add_interface_port $port ${port}_awlen awlen Output "8-(4*DMA_AXI_PROTOCOL_${suffix})" + add_interface_port $port ${port}_awsize awsize Output 3 + add_interface_port $port ${port}_awburst awburst Output 2 + add_interface_port $port ${port}_awcache awcache Output 4 + add_interface_port $port ${port}_awprot awprot Output 3 + add_interface_port $port ${port}_wlast wlast Output 1 + add_interface_port $port ${port}_arlen arlen Output "8-(4*DMA_AXI_PROTOCOL_${suffix})" + add_interface_port $port ${port}_arsize arsize Output 3 + add_interface_port $port ${port}_arburst arburst Output 2 + add_interface_port $port ${port}_arcache arcache Output 4 + add_interface_port $port ${port}_arprot arprot Output 3 + # Some signals are mandatory in Altera's implementation of AXI3 + # awid, awlock, wid, bid, arid, arlock, rid, rlast + # Hide them in AXI4 + add_interface_port $port ${port}_awid awid Output 1 + add_interface_port $port ${port}_awlock awlock Output "1+DMA_AXI_PROTOCOL_${suffix}" + add_interface_port $port ${port}_wid wid Output 1 + add_interface_port $port ${port}_arid arid Output 1 + add_interface_port $port ${port}_arlock arlock Output "1+DMA_AXI_PROTOCOL_${suffix}" + add_interface_port $port ${port}_rid rid Input 1 + add_interface_port $port ${port}_bid bid Input 1 + add_interface_port $port ${port}_rlast rlast Input 1 + if {$axi_type == "axi4"} { + set_port_property ${port}_awid TERMINATION true + set_port_property ${port}_awlock TERMINATION true + set_port_property ${port}_wid TERMINATION true + set_port_property ${port}_arid TERMINATION true + set_port_property ${port}_arlock TERMINATION true + set_port_property ${port}_rid TERMINATION true + set_port_property ${port}_bid TERMINATION true + if {$port == "m_dest_axi"} { + set_port_property ${port}_rlast TERMINATION true + } + } +} +proc axi_dmac_elaborate {} { + set fifo_size [get_parameter_value FIFO_SIZE] + set disabled_intfs {} + + # add axi3 or axi4 interface depending on user selection + foreach {suffix port} {SRC m_src_axi DEST m_dest_axi} { + if {[get_parameter_value DMA_AXI_PROTOCOL_${suffix}] == 0} { + set axi_type axi4 + } else { + set axi_type axi + } + add_axi_master_interface $axi_type $port $suffix + } + + # axi4 destination/source + + if {[get_parameter_value DMA_TYPE_DEST] == 0} { + set_interface_property m_dest_axi writeIssuingCapability $fifo_size + set_interface_property m_dest_axi combinedIssuingCapability $fifo_size + } else { + lappend disabled_intfs m_dest_axi_clock m_dest_axi_reset m_dest_axi + } + + if {[get_parameter_value DMA_TYPE_SRC] == 0} { + set_interface_property m_src_axi readIssuingCapability $fifo_size + set_interface_property m_src_axi combinedIssuingCapability $fifo_size + } else { + lappend disabled_intfs m_src_axi_clock m_src_axi_reset m_src_axi + } + + # axis destination/source + + if {[get_parameter_value DMA_TYPE_DEST] != 1} { + lappend disabled_intfs \ + if_m_axis_aclk if_m_axis_valid if_m_axis_data if_m_axis_ready \ + if_m_axis_last if_m_axis_xfer_req + } + + if {[get_parameter_value DMA_TYPE_DEST] == 1 && + [get_parameter_value USE_TLAST_DEST] == 0} { + set_port_property m_axis_last termination true + } + + if {[get_parameter_value DMA_TYPE_SRC] != 1} { + lappend disabled_intfs \ + if_s_axis_aclk if_s_axis_valid if_s_axis_data if_s_axis_ready \ + if_s_axis_xfer_req if_s_axis_user if_s_axis_last + } + + if {[get_parameter_value DMA_TYPE_SRC] == 1 && + [get_parameter_value SYNC_TRANSFER_START] == 0} { + set_port_property s_axis_user termination true + set_port_property s_axis_user termination_value 1 + } + + if {[get_parameter_value DMA_TYPE_SRC] == 1 && + [get_parameter_value USE_TLAST_SRC] == 0} { + set_port_property s_axis_last termination true + set_port_property s_axis_last termination_value 0 + } + + # fifo destination/source + + if {[get_parameter_value DMA_TYPE_DEST] != 2} { + lappend disabled_intfs \ + if_fifo_rd_clk if_fifo_rd_en if_fifo_rd_valid if_fifo_rd_dout \ + if_fifo_rd_underflow if_fifo_rd_xfer_req + } + + if {[get_parameter_value DMA_TYPE_SRC] != 2} { + lappend disabled_intfs \ + if_fifo_wr_clk if_fifo_wr_en if_fifo_wr_din if_fifo_wr_overflow \ + if_fifo_wr_sync if_fifo_wr_xfer_req + } + + if {[get_parameter_value DMA_TYPE_SRC] == 2 && + [get_parameter_value SYNC_TRANSFER_START] == 0} { + set_port_property fifo_wr_sync termination true + set_port_property fifo_wr_sync termination_value 1 + } + + if {[get_parameter_value ENABLE_DIAGNOSTICS_IF] != 1} { + lappend disabled_intfs diagnostics_if + } + + foreach intf $disabled_intfs { + set_interface_property $intf ENABLED false + } +} + +set group "Debug" + +add_parameter DISABLE_DEBUG_REGISTERS INTEGER 0 +set_parameter_property DISABLE_DEBUG_REGISTERS DISPLAY_NAME "Disable debug registers" +set_parameter_property DISABLE_DEBUG_REGISTERS DISPLAY_HINT boolean +set_parameter_property DISABLE_DEBUG_REGISTERS HDL_PARAMETER false +set_parameter_property DISABLE_DEBUG_REGISTERS GROUP $group + +add_parameter ENABLE_DIAGNOSTICS_IF INTEGER 0 +set_parameter_property ENABLE_DIAGNOSTICS_IF DISPLAY_NAME "Enable Diagnostics Interface" +set_parameter_property ENABLE_DIAGNOSTICS_IF DISPLAY_HINT boolean +set_parameter_property ENABLE_DIAGNOSTICS_IF HDL_PARAMETER true +set_parameter_property ENABLE_DIAGNOSTICS_IF GROUP $group + +add_interface diagnostics_if conduit end +add_interface_port diagnostics_if dest_diag_level_bursts dest_diag_level_bursts Output "8" diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_ip.tcl b/src/adi/hdl/library/axi_dmac/axi_dmac_ip.tcl new file mode 100644 index 00000000..7e831347 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_ip.tcl @@ -0,0 +1,400 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_dmac +adi_ip_files axi_dmac [list \ + "$ad_hdl_dir/library/common/ad_mem.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "inc_id.vh" \ + "resp.vh" \ + "axi_dmac_burst_memory.v" \ + "axi_dmac_regmap.v" \ + "axi_dmac_regmap_request.v" \ + "axi_dmac_reset_manager.v" \ + "axi_dmac_resize_dest.v" \ + "axi_dmac_resize_src.v" \ + "axi_dmac_response_manager.v" \ + "axi_dmac_transfer.v" \ + "address_generator.v" \ + "data_mover.v" \ + "request_arb.v" \ + "request_generator.v" \ + "response_handler.v" \ + "axi_register_slice.v" \ + "2d_transfer.v" \ + "dest_axi_mm.v" \ + "dest_axi_stream.v" \ + "dest_fifo_inf.v" \ + "src_axi_mm.v" \ + "src_axi_stream.v" \ + "src_fifo_inf.v" \ + "splitter.v" \ + "response_generator.v" \ + "axi_dmac.v" \ + "axi_dmac_constr.ttcl" \ + "axi_dmac_pkg_sv.ttcl" \ + "bd/bd.tcl" ] + +adi_ip_properties axi_dmac +adi_ip_infer_mm_interfaces axi_dmac +adi_ip_ttcl axi_dmac "axi_dmac_constr.ttcl" +adi_ip_sim_ttcl axi_dmac "axi_dmac_pkg_sv.ttcl" +adi_ip_bd axi_dmac "bd/bd.tcl" + +adi_ip_add_core_dependencies { \ + analog.com:user:util_axis_fifo:1.0 \ + analog.com:user:util_cdc:1.0 \ +} + +set_property display_name "ADI AXI DMA Controller" [ipx::current_core] +set_property description "ADI AXI DMA Controller" [ipx::current_core] + +adi_add_bus "s_axis" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"s_axis_ready" "TREADY"} \ + {"s_axis_valid" "TVALID"} \ + {"s_axis_data" "TDATA"} \ + {"s_axis_last" "TLAST"} \ + {"s_axis_user" "TUSER"} ] +adi_add_bus_clock "s_axis_aclk" "s_axis" + +adi_add_bus "m_axis" "master" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"m_axis_ready" "TREADY"} \ + {"m_axis_valid" "TVALID"} \ + {"m_axis_data" "TDATA"} \ + {"m_axis_last" "TLAST"} ] +adi_add_bus_clock "m_axis_aclk" "m_axis" + +adi_set_bus_dependency "m_src_axi" "m_src_axi" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_SRC')) = 0)" +adi_set_bus_dependency "m_dest_axi" "m_dest_axi" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_DEST')) = 0)" +adi_set_bus_dependency "s_axis" "s_axis" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_SRC')) = 1)" +adi_set_bus_dependency "m_axis" "m_axis" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_DEST')) = 1)" +adi_set_ports_dependency "fifo_rd" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_DEST')) = 2)" +adi_set_ports_dependency "dest_diag_level_bursts" \ + "(spirit:decode(id('MODELPARAM_VALUE.ENABLE_DIAGNOSTICS_IF')) = 1)" + +# These are in the design to keep the Altera tools happy which can't handle +# uni-directional AXI interfaces. The Xilinx tools can and do a better job when +# they know that the interface is uni-directional, so disable the ports. +set dummy_axi_ports [list \ + "m_dest_axi_arvalid" \ + "m_dest_axi_arready" \ + "m_dest_axi_araddr" \ + "m_dest_axi_arlen" \ + "m_dest_axi_arsize" \ + "m_dest_axi_arburst" \ + "m_dest_axi_arcache" \ + "m_dest_axi_arprot" \ + "m_dest_axi_rready" \ + "m_dest_axi_rvalid" \ + "m_dest_axi_rresp" \ + "m_dest_axi_rdata" \ + "m_src_axi_awvalid" \ + "m_src_axi_awready" \ + "m_src_axi_awvalid" \ + "m_src_axi_awaddr" \ + "m_src_axi_awlen" \ + "m_src_axi_awsize" \ + "m_src_axi_awburst" \ + "m_src_axi_awcache" \ + "m_src_axi_awprot" \ + "m_src_axi_wvalid" \ + "m_src_axi_wready" \ + "m_src_axi_wvalid" \ + "m_src_axi_wdata" \ + "m_src_axi_wstrb" \ + "m_src_axi_wlast" \ + "m_src_axi_bready" \ + "m_src_axi_bvalid" \ + "m_src_axi_bresp" \ +] + +# These are in the design to keep the Altera tools happy which require +# certain signals in AXI3 mode even if these are defined as optinal in the standard. +lappend dummy_axi_ports \ + "m_dest_axi_awid" \ + "m_dest_axi_awlock" \ + "m_dest_axi_wid" \ + "m_dest_axi_bid" \ + "m_dest_axi_arid" \ + "m_dest_axi_arlock" \ + "m_dest_axi_rid" \ + "m_dest_axi_rlast" \ + "m_src_axi_arid" \ + "m_src_axi_arlock" \ + "m_src_axi_rid" \ + "m_src_axi_awid" \ + "m_src_axi_awlock" \ + "m_src_axi_wid" \ + "m_src_axi_bid" + + +foreach p $dummy_axi_ports { + adi_set_ports_dependency $p "false" +} + +set_property master_address_space_ref m_dest_axi \ + [ipx::get_bus_interfaces m_dest_axi \ + -of_objects [ipx::current_core]] +set_property master_address_space_ref m_src_axi \ + [ipx::get_bus_interfaces m_src_axi \ + -of_objects [ipx::current_core]] + +adi_add_bus "fifo_wr" "slave" \ + "analog.com:interface:fifo_wr_rtl:1.0" \ + "analog.com:interface:fifo_wr:1.0" \ + { \ + {"fifo_wr_en" "EN"} \ + {"fifo_wr_din" "DATA"} \ + {"fifo_wr_overflow" "OVERFLOW"} \ + {"fifo_wr_sync" "SYNC"} \ + {"fifo_wr_xfer_req" "XFER_REQ"} \ + } + +adi_add_bus_clock "fifo_wr_clk" "fifo_wr" + +adi_set_bus_dependency "fifo_wr" "fifo_wr" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_SRC')) = 2)" + +adi_add_bus "fifo_rd" "slave" \ + "analog.com:interface:fifo_rd_rtl:1.0" \ + "analog.com:interface:fifo_rd:1.0" \ + { + {"fifo_rd_en" "EN"} \ + {"fifo_rd_dout" "DATA"} \ + {"fifo_rd_valid" "VALID"} \ + {"fifo_rd_underflow" "UNDERFLOW"} \ + } + +adi_add_bus_clock "fifo_rd_clk" "fifo_rd" + +adi_set_bus_dependency "fifo_rd" "fifo_rd" \ + "(spirit:decode(id('MODELPARAM_VALUE.DMA_TYPE_DEST')) = 2)" + +foreach port {"m_dest_axi_aresetn" "m_src_axi_aresetn" \ + "s_axis_valid" "s_axis_data" "s_axis_last" "m_axis_ready" \ + "fifo_wr_en" "fifo_wr_din" "fifo_rd_en"} { + set_property DRIVER_VALUE "0" [ipx::get_ports $port] +} + +foreach port {"s_axis_user" "fifo_wr_sync"} { + set_property DRIVER_VALUE "1" [ipx::get_ports $port] +} + +# Infer interrupt +ipx::infer_bus_interface irq xilinx.com:signal:interrupt_rtl:1.0 [ipx::current_core] + +set cc [ipx::current_core] + +# The core does not issue narrow bursts +foreach intf [ipx::get_bus_interfaces m_*_axi -of_objects $cc] { + set para [ipx::add_bus_parameter SUPPORTS_NARROW_BURST $intf] + set_property "VALUE" "0" $para +} + +set_property -dict [list \ + "value_validation_type" "list" \ + "value_validation_list" "2 4 8 16 32" \ + ] \ + [ipx::get_user_parameters FIFO_SIZE -of_objects $cc] + +set_property -dict [list \ + "value_validation_type" "range_long" \ + "value_validation_range_minimum" "8" \ + "value_validation_range_maximum" "32" \ + ] \ + [ipx::get_user_parameters DMA_LENGTH_WIDTH -of_objects $cc] + +foreach {k v} { \ + "ASYNC_CLK_REQ_SRC" "true" \ + "ASYNC_CLK_SRC_DEST" "true" \ + "ASYNC_CLK_DEST_REQ" "true" \ + "CYCLIC" "false" \ + "DMA_2D_TRANSFER" "false" \ + "SYNC_TRANSFER_START" "false" \ + "AXI_SLICE_SRC" "false" \ + "AXI_SLICE_DEST" "false" \ + "DISABLE_DEBUG_REGISTERS" "false" \ + "ENABLE_DIAGNOSTICS_IF" "false" \ + } { \ + set_property -dict [list \ + "value_format" "bool" \ + "value" $v \ + ] \ + [ipx::get_user_parameters $k -of_objects $cc] + set_property -dict [list \ + "value_format" "bool" \ + "value" $v \ + ] \ + [ipx::get_hdl_parameters $k -of_objects $cc] +} + +set_property -dict [list \ + "enablement_tcl_expr" "\$DMA_TYPE_SRC != 0" \ +] \ +[ipx::get_user_parameters SYNC_TRANSFER_START -of_objects $cc] + +foreach dir {"SRC" "DEST"} { + set_property -dict [list \ + "value_validation_type" "list" \ + "value_validation_list" "16 32 64 128 256 512 1024" \ + ] \ + [ipx::get_user_parameters DMA_DATA_WIDTH_${dir} -of_objects $cc] + + set_property -dict [list \ + "value_validation_type" "pairs" \ + "value_validation_pairs" {"AXI3" "1" "AXI4" "0"} \ + "enablement_tcl_expr" "\$DMA_TYPE_${dir} == 0" \ + ] \ + [ipx::get_user_parameters DMA_AXI_PROTOCOL_${dir} -of_objects $cc] + + set_property -dict [list \ + "value_validation_type" "pairs" \ + "value_validation_pairs" { \ + "Memory-Mapped AXI" "0" \ + "Streaming AXI" "1" \ + "FIFO Interface" "2" \ + } \ + ] \ + [ipx::get_user_parameters DMA_TYPE_${dir} -of_objects $cc] +} + +set page0 [ipgui::get_pagespec -name "Page 0" -component $cc] +set g [ipgui::add_group -name {DMA Endpoint Configuration} -component $cc \ + -parent $page0 -display_name {DMA Endpoint Configuration} \ + -layout "horizontal"] +set src_group [ipgui::add_group -name {Source} -component $cc -parent $g \ + -display_name {Source}] +set dest_group [ipgui::add_group -name {Destination} -component $cc -parent $g \ + -display_name {Destination}] + +foreach {dir group} [list "SRC" $src_group "DEST" $dest_group] { + set p [ipgui::get_guiparamspec -name "DMA_TYPE_${dir}" -component $cc] + ipgui::move_param -component $cc -order 0 $p -parent $group + set_property -dict [list \ + "widget" "comboBox" \ + "display_name" "Type" \ + ] $p + + set p [ipgui::get_guiparamspec -name "DMA_AXI_PROTOCOL_${dir}" -component $cc] + ipgui::move_param -component $cc -order 1 $p -parent $group + set_property -dict [list \ + "widget" "comboBox" \ + "display_name" "AXI Protocol" \ + ] $p + + set p [ipgui::get_guiparamspec -name "DMA_DATA_WIDTH_${dir}" -component $cc] + ipgui::move_param -component $cc -order 2 $p -parent $group + set_property -dict [list \ + "display_name" "Bus Width" \ + ] $p + + set p [ipgui::get_guiparamspec -name "AXI_SLICE_${dir}" -component $cc] + ipgui::move_param -component $cc -order 3 $p -parent $group + set_property -dict [list \ + "display_name" "Insert Register Slice" \ + ] $p +} + +set p [ipgui::get_guiparamspec -name "SYNC_TRANSFER_START" -component $cc] +ipgui::move_param -component $cc -order 4 $p -parent $src_group +set_property -dict [list \ + "display_name" "Transfer Start Synchronization Support" \ +] $p + +set general_group [ipgui::add_group -name "General Configuration" -component $cc \ + -parent $page0 -display_name "General Configuration"] + +set p [ipgui::get_guiparamspec -name "ID" -component $cc] +ipgui::move_param -component $cc -order 0 $p -parent $general_group +set_property -dict [list \ + "display_name" "Core ID" \ +] $p + +set p [ipgui::get_guiparamspec -name "DMA_LENGTH_WIDTH" -component $cc] +ipgui::move_param -component $cc -order 1 $p -parent $general_group +set_property -dict [list \ + "display_name" "DMA Transfer Length Register Width" \ +] $p + +set p [ipgui::get_guiparamspec -name "FIFO_SIZE" -component $cc] +ipgui::move_param -component $cc -order 2 $p -parent $general_group +set_property -dict [list \ + "widget" "comboBox" \ + "display_name" "Store-and-Forward Memory Size (In Bursts)" \ +] $p + +set p [ipgui::get_guiparamspec -name "MAX_BYTES_PER_BURST" -component $cc] +ipgui::move_param -component $cc -order 3 $p -parent $general_group +set_property -dict [list \ + "display_name" "Maximum Bytes per Burst" \ +] $p + +set feature_group [ipgui::add_group -name "Features" -component $cc \ + -parent $page0 -display_name "Features"] + +set p [ipgui::get_guiparamspec -name "CYCLIC" -component $cc] +ipgui::move_param -component $cc -order 0 $p -parent $feature_group +set_property -dict [list \ + "display_name" "Cyclic Transfer Support" \ +] $p + +set p [ipgui::get_guiparamspec -name "DMA_2D_TRANSFER" -component $cc] +ipgui::move_param -component $cc -order 1 $p -parent $feature_group +set_property -dict [list \ + "display_name" "2D Transfer Support" \ +] $p + +set clk_group [ipgui::add_group -name {Clock Domain Configuration} -component $cc \ + -parent $page0 -display_name {Clock Domain Configuration}] + +set p [ipgui::get_guiparamspec -name "ASYNC_CLK_REQ_SRC" -component $cc] +ipgui::move_param -component $cc -order 0 $p -parent $clk_group +set_property -dict [list \ + "display_name" "Request and Source Clock Asynchronous" \ +] $p + +set p [ipgui::get_guiparamspec -name "ASYNC_CLK_SRC_DEST" -component $cc] +ipgui::move_param -component $cc -order 1 $p -parent $clk_group +set_property -dict [list \ + "display_name" "Source and Destination Clock Asynchronous" \ +] $p + +set p [ipgui::get_guiparamspec -name "ASYNC_CLK_DEST_REQ" -component $cc] +ipgui::move_param -component $cc -order 2 $p -parent $clk_group +set_property -dict [list \ + "display_name" "Destination and Request Clock Asynchronous" \ +] $p + +set dbg_group [ipgui::add_group -name {Debug} -component $cc \ + -parent $page0 -display_name {Debug}] + +set p [ipgui::get_guiparamspec -name "DISABLE_DEBUG_REGISTERS" -component $cc] +ipgui::move_param -component $cc -order 0 $p -parent $dbg_group +set_property -dict [list \ + "display_name" "Disable Debug Registers" \ +] $p + +set p [ipgui::get_guiparamspec -name "ENABLE_DIAGNOSTICS_IF" -component $cc] +ipgui::move_param -component $cc -order 1 $p -parent $dbg_group +set_property -dict [list \ + "display_name" "Enable Diagnostics Interface" \ +] $p + +ipgui::remove_param -component $cc [ipgui::get_guiparamspec -name "DMA_AXI_ADDR_WIDTH" -component $cc] +ipgui::remove_param -component $cc [ipgui::get_guiparamspec -name "AXI_ID_WIDTH_SRC" -component $cc] +ipgui::remove_param -component $cc [ipgui::get_guiparamspec -name "AXI_ID_WIDTH_DEST" -component $cc] + + +ipx::create_xgui_files [ipx::current_core] +ipx::save_core $cc diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_pkg_sv.ttcl b/src/adi/hdl/library/axi_dmac/axi_dmac_pkg_sv.ttcl new file mode 100644 index 00000000..30572ad0 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_pkg_sv.ttcl @@ -0,0 +1,64 @@ +<: :> +<: set ComponentName [getComponentNameString] :> +<: setOutputDirectory "./sim/" :> +<: setFileName ${ComponentName}_pkg :> +<: setFileExtension ".sv" :> +<: set id [get_property MODELPARAM_VALUE.ID] :> +<: set dma_data_width_src [get_property MODELPARAM_VALUE.DMA_DATA_WIDTH_SRC] :> +<: set dma_data_width_dest [get_property MODELPARAM_VALUE.DMA_DATA_WIDTH_DEST] :> +<: set dma_length_width [get_property MODELPARAM_VALUE.DMA_LENGTH_WIDTH] :> +<: set dma_2d_transfer [get_property MODELPARAM_VALUE.DMA_2D_TRANSFER] :> +<: set async_clk_req_src [get_property MODELPARAM_VALUE.ASYNC_CLK_REQ_SRC] :> +<: set async_clk_src_dest [get_property MODELPARAM_VALUE.ASYNC_CLK_SRC_DEST] :> +<: set async_clk_dest_req [get_property MODELPARAM_VALUE.ASYNC_CLK_DEST_REQ] :> +<: set axi_slice_dest [get_property MODELPARAM_VALUE.AXI_SLICE_DEST] :> +<: set axi_slice_src [get_property MODELPARAM_VALUE.AXI_SLICE_SRC] :> +<: set sync_transfer_start [get_property MODELPARAM_VALUE.SYNC_TRANSFER_START] :> +<: set cyclic [get_property MODELPARAM_VALUE.CYCLIC] :> +<: set dma_axi_protocol_dest [get_property MODELPARAM_VALUE.DMA_AXI_PROTOCOL_DEST] :> +<: set dma_axi_protocol_src [get_property MODELPARAM_VALUE.DMA_AXI_PROTOCOL_SRC] :> +<: set dma_type_dest [get_property MODELPARAM_VALUE.DMA_TYPE_DEST] :> +<: set dma_type_src [get_property MODELPARAM_VALUE.DMA_TYPE_SRC] :> +<: set dma_axi_addr_width [get_property MODELPARAM_VALUE.DMA_AXI_ADDR_WIDTH] :> +<: set max_bytes_per_burst [get_property MODELPARAM_VALUE.MAX_BYTES_PER_BURST] :> +<: set fifo_size [get_property MODELPARAM_VALUE.FIFO_SIZE] :> +<: set axi_id_width_src [get_property MODELPARAM_VALUE.AXI_ID_WIDTH_SRC] :> +<: set axi_id_width_dest [get_property MODELPARAM_VALUE.AXI_ID_WIDTH_DEST] :> +<: set disable_debug_registers [get_property MODELPARAM_VALUE.DISABLE_DEBUG_REGISTERS] :> + +<: proc b2i {b} { if {$b==true} {return 1} else {return 0}} :> +/////////////////////////////////////////////////////////////////////////// +//NOTE: This file has been automatically generated by Vivado. +/////////////////////////////////////////////////////////////////////////// + +package <=: ComponentName :>_pkg; + +/////////////////////////////////////////////////////////////////////////// +// These parameters are named after the component for use in your verification +// environment. +/////////////////////////////////////////////////////////////////////////// + parameter <=: ComponentName :>_ID = <=: $id :>; + parameter <=: ComponentName :>_DMA_DATA_WIDTH_SRC = <=: $dma_data_width_src :>; + parameter <=: ComponentName :>_DMA_DATA_WIDTH_DEST = <=: $dma_data_width_dest :>; + parameter <=: ComponentName :>_DMA_LENGTH_WIDTH = <=: $dma_length_width :>; + parameter <=: ComponentName :>_DMA_2D_TRANSFER = <=: b2i $dma_2d_transfer :>; + parameter <=: ComponentName :>_ASYNC_CLK_REQ_SRC = <=: b2i $async_clk_req_src :>; + parameter <=: ComponentName :>_ASYNC_CLK_SRC_DEST = <=: b2i $async_clk_src_dest :>; + parameter <=: ComponentName :>_ASYNC_CLK_DEST_REQ = <=: b2i $async_clk_dest_req :>; + parameter <=: ComponentName :>_AXI_SLICE_DEST = <=: b2i $axi_slice_dest :>; + parameter <=: ComponentName :>_AXI_SLICE_SRC = <=: b2i $axi_slice_src :>; + parameter <=: ComponentName :>_SYNC_TRANSFER_START = <=: b2i $sync_transfer_start :>; + parameter <=: ComponentName :>_CYCLIC = <=: b2i $cyclic :>; + parameter <=: ComponentName :>_DMA_AXI_PROTOCOL_DEST = <=: $dma_axi_protocol_dest :>; + parameter <=: ComponentName :>_DMA_AXI_PROTOCOL_SRC = <=: $dma_axi_protocol_src :>; + parameter <=: ComponentName :>_DMA_TYPE_DEST = <=: $dma_type_dest :>; + parameter <=: ComponentName :>_DMA_TYPE_SRC = <=: $dma_type_src :>; + parameter <=: ComponentName :>_DMA_AXI_ADDR_WIDTH = <=: $dma_axi_addr_width :>; + parameter <=: ComponentName :>_MAX_BYTES_PER_BURST = <=: $max_bytes_per_burst :>; + parameter <=: ComponentName :>_FIFO_SIZE = <=: $fifo_size :>; + parameter <=: ComponentName :>_AXI_ID_WIDTH_SRC = <=: $axi_id_width_src :>; + parameter <=: ComponentName :>_AXI_ID_WIDTH_DEST = <=: $axi_id_width_dest :>; + parameter <=: ComponentName :>_DISABLE_DEBUG_REGISTERS = <=: b2i $disable_debug_registers :>; +////////////////////////////////////////////////////////////////////////// + +endpackage : <=: ComponentName :>_pkg diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_regmap.v b/src/adi/hdl/library/axi_dmac/axi_dmac_regmap.v new file mode 100644 index 00000000..5f8bfafb --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_regmap.v @@ -0,0 +1,296 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_regmap #( + parameter ID = 0, + parameter DISABLE_DEBUG_REGISTERS = 0, + parameter BYTES_PER_BEAT_WIDTH_DEST = 1, + parameter BYTES_PER_BEAT_WIDTH_SRC = 1, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter DMA_LENGTH_WIDTH = 24, + parameter DMA_LENGTH_ALIGN = 3, + parameter DMA_CYCLIC = 0, + parameter HAS_DEST_ADDR = 1, + parameter HAS_SRC_ADDR = 1, + parameter DMA_2D_TRANSFER = 0, + parameter SYNC_TRANSFER_START = 0 +) ( + // Slave AXI interface + input s_axi_aclk, + input s_axi_aresetn, + + input s_axi_awvalid, + output s_axi_awready, + input [11:0] s_axi_awaddr, + input [2:0] s_axi_awprot, + + input s_axi_wvalid, + output s_axi_wready, + input [31:0] s_axi_wdata, + input [3:0] s_axi_wstrb, + + output s_axi_bvalid, + input s_axi_bready, + output [1:0] s_axi_bresp, + + input s_axi_arvalid, + output s_axi_arready, + input [11:0] s_axi_araddr, + input [2:0] s_axi_arprot, + + output s_axi_rvalid, + input s_axi_rready, + output [1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + + // Interrupt + output reg irq, + + // Control interface + output reg ctrl_enable = 1'b0, + output reg ctrl_pause = 1'b0, + + // DMA request interface + output request_valid, + input request_ready, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] request_dest_address, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] request_src_address, + output [DMA_LENGTH_WIDTH-1:0] request_x_length, + output [DMA_LENGTH_WIDTH-1:0] request_y_length, + output [DMA_LENGTH_WIDTH-1:0] request_dest_stride, + output [DMA_LENGTH_WIDTH-1:0] request_src_stride, + output request_sync_transfer_start, + output request_last, + + // DMA response interface + input response_eot, + input [BYTES_PER_BURST_WIDTH-1:0] response_measured_burst_length, + input response_partial, + input response_valid, + output response_ready, + + // Debug interface + input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr, + input [DMA_AXI_ADDR_WIDTH-1:0] dbg_dest_addr, + input [11:0] dbg_status, + input [31:0] dbg_ids0, + input [31:0] dbg_ids1 +); + +localparam PCORE_VERSION = 'h00040261; + +// Register interface signals +reg [31:0] up_rdata = 32'h00; +reg up_wack = 1'b0; +reg up_rack = 1'b0; + +wire up_wreq; +wire up_rreq; +wire [31:0] up_wdata; +wire [8:0] up_waddr; +wire [8:0] up_raddr; +wire [31:0] up_rdata_request; + +// Scratch register +reg [31:0] up_scratch = 32'h00; + +// Start and end of transfer +wire up_eot; // Asserted for one cycle when a transfer has been completed +wire up_sot; // Asserted for one cycle when a transfer has been queued + +// Interupt handling +reg [1:0] up_irq_mask = 2'h3; +reg [1:0] up_irq_source = 2'h0; + +wire [1:0] up_irq_pending; +wire [1:0] up_irq_trigger; +wire [1:0] up_irq_source_clear; + +// IRQ handling +assign up_irq_pending = ~up_irq_mask & up_irq_source; +assign up_irq_trigger = {up_eot, up_sot}; +assign up_irq_source_clear = (up_wreq == 1'b1 && up_waddr == 9'h021) ? up_wdata[1:0] : 2'b00; + +always @(posedge s_axi_aclk) begin + if (s_axi_aresetn == 1'b0) begin + irq <= 1'b0; + end else begin + irq <= |up_irq_pending; + end +end + +always @(posedge s_axi_aclk) begin + if (s_axi_aresetn == 1'b0) begin + up_irq_source <= 2'b00; + end else begin + up_irq_source <= up_irq_trigger | (up_irq_source & ~up_irq_source_clear); + end +end + +// Register Interface + +always @(posedge s_axi_aclk) begin + if (s_axi_aresetn == 1'b0) begin + ctrl_enable <= 1'b0; + ctrl_pause <= 1'b0; + up_irq_mask <= 2'b11; + up_scratch <= 32'h00; + up_wack <= 1'b0; + end else begin + up_wack <= up_wreq; + + if (up_wreq == 1'b1) begin + case (up_waddr) + 9'h002: up_scratch <= up_wdata; + 9'h020: up_irq_mask <= up_wdata[1:0]; + 9'h100: {ctrl_pause, ctrl_enable} <= up_wdata[1:0]; + endcase + end + end +end + +always @(posedge s_axi_aclk) begin + if (s_axi_aresetn == 1'b0) begin + up_rack <= 'd0; + end else begin + up_rack <= up_rreq; + end +end + +always @(posedge s_axi_aclk) begin + if (up_rreq == 1'b1) begin + case (up_raddr) + 9'h000: up_rdata <= PCORE_VERSION; + 9'h001: up_rdata <= ID; + 9'h002: up_rdata <= up_scratch; + 9'h003: up_rdata <= 32'h444d4143; // "DMAC" + 9'h020: up_rdata <= up_irq_mask; + 9'h021: up_rdata <= up_irq_pending; + 9'h022: up_rdata <= up_irq_source; + 9'h100: up_rdata <= {ctrl_pause, ctrl_enable}; + 9'h10d: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_dest_addr; + 9'h10e: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_src_addr; + 9'h10f: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_status; + 9'h110: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_ids0; + 9'h111: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_ids1; + default: up_rdata <= up_rdata_request; + endcase + end +end + +axi_dmac_regmap_request #( + .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), + .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), + .DMA_CYCLIC(DMA_CYCLIC), + .HAS_DEST_ADDR(HAS_DEST_ADDR), + .HAS_SRC_ADDR(HAS_SRC_ADDR), + .DMA_2D_TRANSFER(DMA_2D_TRANSFER), + .SYNC_TRANSFER_START(SYNC_TRANSFER_START) +) i_regmap_request ( + .clk(s_axi_aclk), + .reset(~s_axi_aresetn), + + .up_sot(up_sot), + .up_eot(up_eot), + + .up_wreq(up_wreq), + .up_rreq(up_rreq), + .up_waddr(up_waddr), + .up_wdata(up_wdata), + .up_raddr(up_raddr), + .up_rdata(up_rdata_request), + + .ctrl_enable(ctrl_enable), + + .request_valid(request_valid), + .request_ready(request_ready), + .request_dest_address(request_dest_address), + .request_src_address(request_src_address), + .request_x_length(request_x_length), + .request_y_length(request_y_length), + .request_dest_stride(request_dest_stride), + .request_src_stride(request_src_stride), + .request_sync_transfer_start(request_sync_transfer_start), + .request_last(request_last), + + .response_eot(response_eot), + .response_measured_burst_length(response_measured_burst_length), + .response_partial(response_partial), + .response_valid(response_valid), + .response_ready(response_ready) +); + +up_axi #( + .AXI_ADDRESS_WIDTH (12), + .ADDRESS_WIDTH (9) +) i_up_axi ( + .up_rstn(s_axi_aresetn), + .up_clk(s_axi_aclk), + .up_axi_awvalid(s_axi_awvalid), + .up_axi_awaddr(s_axi_awaddr), + .up_axi_awready(s_axi_awready), + .up_axi_wvalid(s_axi_wvalid), + .up_axi_wdata(s_axi_wdata), + .up_axi_wstrb(s_axi_wstrb), + .up_axi_wready(s_axi_wready), + .up_axi_bvalid(s_axi_bvalid), + .up_axi_bresp(s_axi_bresp), + .up_axi_bready(s_axi_bready), + .up_axi_arvalid(s_axi_arvalid), + .up_axi_araddr(s_axi_araddr), + .up_axi_arready(s_axi_arready), + .up_axi_rvalid(s_axi_rvalid), + .up_axi_rresp(s_axi_rresp), + .up_axi_rdata(s_axi_rdata), + .up_axi_rready(s_axi_rready), + .up_wreq(up_wreq), + .up_waddr(up_waddr), + .up_wdata(up_wdata), + .up_wack(up_wack), + .up_rreq(up_rreq), + .up_raddr(up_raddr), + .up_rdata(up_rdata), + .up_rack(up_rack) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_regmap_request.v b/src/adi/hdl/library/axi_dmac/axi_dmac_regmap_request.v new file mode 100644 index 00000000..9ff1de2e --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_regmap_request.v @@ -0,0 +1,308 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_regmap_request #( + parameter DISABLE_DEBUG_REGISTERS = 0, + parameter BYTES_PER_BEAT_WIDTH_DEST = 1, + parameter BYTES_PER_BEAT_WIDTH_SRC = 1, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter DMA_LENGTH_WIDTH = 24, + parameter DMA_LENGTH_ALIGN = 3, + parameter DMA_CYCLIC = 0, + parameter HAS_DEST_ADDR = 1, + parameter HAS_SRC_ADDR = 1, + parameter DMA_2D_TRANSFER = 0, + parameter SYNC_TRANSFER_START = 0 +) ( + input clk, + input reset, + + // Interrupts + output up_sot, + output up_eot, + + // Register map interface + input up_wreq, + input up_rreq, + input [8:0] up_waddr, + input [31:0] up_wdata, + input [8:0] up_raddr, + output reg [31:0] up_rdata, + + // Control interface + input ctrl_enable, + + // DMA request interface + output request_valid, + input request_ready, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] request_dest_address, + output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] request_src_address, + output [DMA_LENGTH_WIDTH-1:0] request_x_length, + output [DMA_LENGTH_WIDTH-1:0] request_y_length, + output [DMA_LENGTH_WIDTH-1:0] request_dest_stride, + output [DMA_LENGTH_WIDTH-1:0] request_src_stride, + output request_sync_transfer_start, + output request_last, + + // DMA response interface + input response_eot, + input [BYTES_PER_BURST_WIDTH-1:0] response_measured_burst_length, + input response_partial, + input response_valid, + output reg response_ready = 1'b1 + +); + +localparam MEASURED_LENGTH_WIDTH = (DMA_2D_TRANSFER == 1) ? 32 : DMA_LENGTH_WIDTH; + +// DMA transfer signals +reg up_dma_req_valid = 1'b0; +wire up_dma_req_ready; + +reg [1:0] up_transfer_id = 2'b0; +reg [1:0] up_transfer_id_eot = 2'b0; +reg [3:0] up_transfer_done_bitmap = 4'b0; + +reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] up_dma_dest_address = 'h00; +reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] up_dma_src_address = 'h00; +reg [DMA_LENGTH_WIDTH-1:0] up_dma_x_length = {DMA_LENGTH_ALIGN{1'b1}}; +reg up_dma_cyclic = DMA_CYCLIC ? 1'b1 : 1'b0; +reg up_dma_last = 1'b1; +reg up_dma_enable_tlen_reporting = 1'b0; + +wire up_tlf_s_ready; +reg up_tlf_s_valid = 1'b0; + +wire [MEASURED_LENGTH_WIDTH+2-1:0] up_tlf_data; +wire up_tlf_valid; +wire up_tlf_rd; +reg up_partial_length_valid = 1'b0; + +reg [MEASURED_LENGTH_WIDTH-1:0] up_measured_transfer_length = 'h0; +reg up_clear_tl = 1'b0; +reg [1:0] up_transfer_id_eot_d = 'h0; +wire up_bl_partial; + +assign request_dest_address = up_dma_dest_address; +assign request_src_address = up_dma_src_address; +assign request_x_length = up_dma_x_length; +assign request_sync_transfer_start = SYNC_TRANSFER_START ? 1'b1 : 1'b0; +assign request_last = up_dma_last; + +always @(posedge clk) begin + if (reset == 1'b1) begin + up_dma_src_address <= 'h00; + up_dma_dest_address <= 'h00; + up_dma_x_length[DMA_LENGTH_WIDTH-1:DMA_LENGTH_ALIGN] <= 'h00; + up_dma_req_valid <= 1'b0; + up_dma_cyclic <= DMA_CYCLIC ? 1'b1 : 1'b0; + up_dma_last <= 1'b1; + up_dma_enable_tlen_reporting <= 1'b0; + end else begin + if (ctrl_enable == 1'b1) begin + if (up_wreq == 1'b1 && up_waddr == 9'h102) begin + up_dma_req_valid <= up_dma_req_valid | up_wdata[0]; + end else if (up_sot == 1'b1) begin + up_dma_req_valid <= 1'b0; + end + end else begin + up_dma_req_valid <= 1'b0; + end + + if (up_wreq == 1'b1) begin + case (up_waddr) + 9'h103: begin + if (DMA_CYCLIC) up_dma_cyclic <= up_wdata[0]; + up_dma_last <= up_wdata[1]; + up_dma_enable_tlen_reporting <= up_wdata[2]; + end + 9'h104: up_dma_dest_address <= up_wdata[DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST]; + 9'h105: up_dma_src_address <= up_wdata[DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC]; + 9'h106: up_dma_x_length[DMA_LENGTH_WIDTH-1:DMA_LENGTH_ALIGN] <= up_wdata[DMA_LENGTH_WIDTH-1:DMA_LENGTH_ALIGN]; + endcase + end + end +end + +always @(*) begin + case (up_raddr) + 9'h101: up_rdata <= up_transfer_id; + 9'h102: up_rdata <= up_dma_req_valid; + 9'h103: up_rdata <= {29'h00, up_dma_enable_tlen_reporting, up_dma_last, up_dma_cyclic}; // Flags + 9'h104: up_rdata <= HAS_DEST_ADDR ? {up_dma_dest_address,{BYTES_PER_BEAT_WIDTH_DEST{1'b0}}} : 'h00; + 9'h105: up_rdata <= HAS_SRC_ADDR ? {up_dma_src_address,{BYTES_PER_BEAT_WIDTH_SRC{1'b0}}} : 'h00; + 9'h106: up_rdata <= up_dma_x_length; + 9'h107: up_rdata <= request_y_length; + 9'h108: up_rdata <= request_dest_stride; + 9'h109: up_rdata <= request_src_stride; + 9'h10a: up_rdata <= {up_partial_length_valid,27'b0,up_transfer_done_bitmap}; + 9'h10b: up_rdata <= up_transfer_id_eot; + 9'h10c: up_rdata <= 32'h0; + 9'h112: up_rdata <= up_measured_transfer_length; + 9'h113: up_rdata <= up_tlf_data[MEASURED_LENGTH_WIDTH-1 : 0]; // Length + 9'h114: up_rdata <= up_tlf_data[MEASURED_LENGTH_WIDTH+: 2]; // ID + default: up_rdata <= 32'h00; + endcase +end + +generate +if (DMA_2D_TRANSFER == 1) begin + reg [DMA_LENGTH_WIDTH-1:0] up_dma_y_length = 'h00; + reg [DMA_LENGTH_WIDTH-1:0] up_dma_src_stride = 'h00; + reg [DMA_LENGTH_WIDTH-1:0] up_dma_dest_stride = 'h00; + + always @(posedge clk) begin + if (reset == 1'b1) begin + up_dma_y_length <= 'h00; + up_dma_dest_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] <= 'h00; + up_dma_src_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] <= 'h00; + end else if (up_wreq == 1'b1) begin + case (up_waddr) + 9'h107: up_dma_y_length <= up_wdata[DMA_LENGTH_WIDTH-1:0]; + 9'h108: up_dma_dest_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] <= up_wdata[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST]; + 9'h109: up_dma_src_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] <= up_wdata[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC]; + endcase + end + end + assign request_y_length = up_dma_y_length; + assign request_dest_stride = up_dma_dest_stride; + assign request_src_stride = up_dma_src_stride; +end else begin + assign request_y_length = 'h0; + assign request_dest_stride = 'h0; + assign request_src_stride = 'h0; +end +endgenerate + +// In cyclic mode the same transfer is submitted over and over again +assign up_sot = up_dma_cyclic ? 1'b0 : up_dma_req_valid & up_dma_req_ready; +assign up_eot = up_dma_cyclic ? 1'b0 : response_eot & response_valid & response_ready; + +assign request_valid = up_dma_req_valid; +assign up_dma_req_ready = request_ready; + +// Request ID and Request done bitmap handling +always @(posedge clk) begin + if (ctrl_enable == 1'b0) begin + up_transfer_id <= 2'h0; + up_transfer_id_eot <= 2'h0; + up_transfer_done_bitmap <= 4'h0; + end else begin + if (up_sot == 1'b1) begin + up_transfer_id <= up_transfer_id + 1'b1; + up_transfer_done_bitmap[up_transfer_id] <= 1'b0; + end + + if (up_eot == 1'b1) begin + up_transfer_id_eot <= up_transfer_id_eot + 1'b1; + up_transfer_done_bitmap[up_transfer_id_eot] <= 1'b1; + end + end +end + +assign up_tlf_rd = up_rreq && up_raddr == 'h114; +assign up_bl_partial = response_valid & response_ready & response_partial & up_dma_enable_tlen_reporting; + +always @(posedge clk) begin + if (ctrl_enable == 1'b0) begin + up_partial_length_valid <= 1'b0; + end else begin + if (up_bl_partial == 1'b1) begin + up_partial_length_valid <= 1'b1; + end else if (up_tlf_rd == 1'b1) begin + up_partial_length_valid <= 1'b0; + end else if (up_tlf_valid == 1'b1) begin + up_partial_length_valid <= 1'b1; + end + end +end + +always @(posedge clk) +begin + if (response_valid == 1'b1 & response_ready == 1'b1) begin + up_measured_transfer_length <= up_measured_transfer_length + response_measured_burst_length + 1'b1; + up_transfer_id_eot_d <= up_transfer_id_eot; + end else if (up_clear_tl == 1'b1) begin + up_measured_transfer_length <= 'h0; + end +end + +always @(posedge clk) +begin + if (ctrl_enable == 1'b0) begin + response_ready <= 1'b1; + end else if (response_ready == 1'b1) begin + response_ready <= ~response_valid; + end else if (up_tlf_s_ready == 1'b1) begin + response_ready <= 1'b1; + end +end + +always @(posedge clk) +begin + if (response_valid == 1'b1 && response_ready == 1'b1) begin + up_tlf_s_valid <= up_bl_partial; + up_clear_tl <= up_eot; + end else if (up_tlf_s_ready == 1'b1) begin + up_tlf_s_valid <= 1'b0; + end +end + +// Buffer the length and transfer ID of partial transfers +util_axis_fifo #( + .DATA_WIDTH(MEASURED_LENGTH_WIDTH + 2), + .ADDRESS_WIDTH(2), + .ASYNC_CLK(0) +) i_transfer_lenghts_fifo ( + .s_axis_aclk(clk), + .s_axis_aresetn(ctrl_enable), + .s_axis_valid(up_tlf_s_valid), + .s_axis_ready(up_tlf_s_ready), + .s_axis_empty(), + .s_axis_data({up_transfer_id_eot_d, up_measured_transfer_length}), + .s_axis_room(), + + .m_axis_aclk(clk), + .m_axis_aresetn(ctrl_enable), + .m_axis_valid(up_tlf_valid), + .m_axis_ready(up_tlf_rd & up_tlf_valid), + .m_axis_data(up_tlf_data), + .m_axis_level() +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_reset_manager.v b/src/adi/hdl/library/axi_dmac/axi_dmac_reset_manager.v new file mode 100644 index 00000000..e889e6e8 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_reset_manager.v @@ -0,0 +1,304 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_reset_manager #( + parameter ASYNC_CLK_REQ_SRC = 1, + parameter ASYNC_CLK_SRC_DEST = 1, + parameter ASYNC_CLK_DEST_REQ = 1 +) ( + input clk, + input resetn, + + input ctrl_enable, + input ctrl_pause, + + output req_resetn, + output req_enable, + input req_enabled, + + input dest_clk, + input dest_ext_resetn, + output dest_resetn, + output dest_enable, + input dest_enabled, + + input src_clk, + input src_ext_resetn, + output src_resetn, + output src_enable, + input src_enabled, + + output [11:0] dbg_status +); + +/* + * TODO: + * If an external reset is asserted for a domain that domain will go into reset + * immediately. If a transfer is currently active the transfer will be aborted + * and other domains will be shutdown gracefully. The reset manager will stay in + * the shutdown state until all external resets have been de-asserted. + */ + +localparam STATE_DO_RESET = 3'h0; +localparam STATE_RESET = 3'h1; +localparam STATE_DISABLED = 3'h2; +localparam STATE_STARTUP = 3'h3; +localparam STATE_ENABLED = 3'h4; +localparam STATE_SHUTDOWN = 3'h5; + +reg [2:0] state = 3'b000; +reg needs_reset = 1'b0; +reg do_reset = 1'b0; +reg do_enable = 1'b0; + +wire enabled_dest; +wire enabled_src; + +wire enabled_all; +wire disabled_all; + +assign enabled_all = req_enabled & enabled_src & enabled_dest; +assign disabled_all = ~(req_enabled | enabled_src | enabled_dest); + +assign req_enable = do_enable; + +assign dbg_status = {needs_reset,req_resetn,src_resetn,dest_resetn,1'b0,req_enabled,enabled_src,enabled_dest,1'b0,state}; + +always @(posedge clk) begin + if (state == STATE_DO_RESET) begin + do_reset <= 1'b1; + end else begin + do_reset <= 1'b0; + end +end + +always @(posedge clk) begin + if (state == STATE_STARTUP || state == STATE_ENABLED) begin + do_enable <= 1'b1; + end else begin + do_enable <= 1'b0; + end +end + +/* + * If ctrl_enable goes from 1 to 0 a shutdown procedure is initiated. During the + * shutdown procedure all domains are signaled that a shutdown should occur. The + * domains will then complete any active transactions that are required to + * complete according to the interface semantics. Once a domain has completed + * its transactions it will indicate that it has been shutdown. Once all domains + * indicate that they have been disabled a reset pulse will be generated to all + * domains to clear all residual state. The reset pulse is long enough so that it + * is active in all domains for at least 4 clock cycles. + * + * Once the reset signal is de-asserted the DMA is in an idle state and can be + * enabled again. If the DMA receives a enable while it is performing a shutdown + * sequence it will only be re-enabled once the shutdown sequence has + * successfully completed. + * + * If ctrl_pause is asserted all domains will be disabled. But there will be no + * reset, so when the ctrl_pause signal is de-asserted again the DMA will resume + * with its previous state. + * + */ + +/* + * If ctrl_enable goes low, even for a single clock cycle, we want to go through + * a full reset sequence. This might happen when the state machine is busy, e.g. + * going through a startup sequence. To avoid missing the event store it for + * later. + */ +always @(posedge clk) begin + if (state == STATE_RESET) begin + needs_reset <= 1'b0; + end else if (ctrl_enable == 1'b0) begin + needs_reset <= 1'b1; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + state <= STATE_DO_RESET; + end else begin + case (state) + STATE_DO_RESET: begin + state <= STATE_RESET; + end + STATE_RESET: begin + /* + * Wait for the reset sequence to complete. Stay in this state when + * ctrl_enable == 1'b0, otherwise we'd go through the reset sequence + * again and again. + */ + if (ctrl_enable == 1'b1 && req_resetn == 1'b1) begin + state <= STATE_DISABLED; + end + end + STATE_DISABLED: begin + if (needs_reset == 1'b1) begin + state <= STATE_DO_RESET; + end else if (ctrl_pause == 1'b0) begin + state <= STATE_STARTUP; + end + end + STATE_STARTUP: begin + /* Wait for all domains to be ready */ + if (enabled_all == 1'b1) begin + state <= STATE_ENABLED; + end + end + STATE_ENABLED: begin + if (needs_reset == 1'b1 || ctrl_pause == 1'b1) begin + state <= STATE_SHUTDOWN; + end + end + STATE_SHUTDOWN: begin + /* Wait for all domains to complete outstanding transactions */ + if (disabled_all == 1'b1) begin + state <= STATE_DISABLED; + end + end + endcase + end +end + +/* + * Chain the reset through all clock domains. This makes sure that is asserted + * for at least 4 clock cycles of the slowest domain, no matter what. If + * successive domains have the same clock they'll share their reset signal. + */ + +wire [3:0] reset_async_chain; +wire [3:0] reset_sync_chain; +wire [2:0] reset_chain_clks = {clk, src_clk, dest_clk}; + +localparam GEN_ASYNC_RESET = { + ASYNC_CLK_REQ_SRC ? 1'b1 : 1'b0, + ASYNC_CLK_SRC_DEST ? 1'b1 : 1'b0, + 1'b1 +}; + +assign reset_async_chain[0] = 1'b0; +assign reset_sync_chain[0] = reset_async_chain[3]; + +generate +genvar i; + +for (i = 0; i < 3; i = i + 1) begin: reset_gen + + if (GEN_ASYNC_RESET[i] == 1'b1) begin + + reg [3:0] reset_async = 4'b1111; + reg [1:0] reset_sync = 2'b11; + reg reset_sync_in = 1'b1; + + always @(posedge reset_chain_clks[i] or posedge reset_sync_chain[i]) begin + if (reset_sync_chain[i] == 1'b1) begin + reset_sync_in <= 1'b1; + end else begin + reset_sync_in <= reset_async[0]; + end + end + + always @(posedge reset_chain_clks[i] or posedge do_reset) begin + if (do_reset == 1'b1) begin + reset_async <= 4'b1111; + end else begin + reset_async <= {reset_async_chain[i], reset_async[3:1]}; + end + end + + always @(posedge reset_chain_clks[i]) begin + reset_sync <= {reset_sync_in,reset_sync[1]}; + end + + assign reset_async_chain[i+1] = reset_async[0]; + assign reset_sync_chain[i+1] = reset_sync[0]; + + end else begin + assign reset_async_chain[i+1] = reset_async_chain[i]; + assign reset_sync_chain[i+1] = reset_sync_chain[i]; + end +end + +endgenerate + +/* De-assertions in the opposite direction of the data flow: dest, src, request */ +assign dest_resetn = ~reset_sync_chain[1]; +assign src_resetn = ~reset_sync_chain[2]; +assign req_resetn = ~reset_sync_chain[3]; + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_DEST_REQ) +) i_sync_control_dest ( + .out_clk (dest_clk), + .out_resetn (1'b1), + .in (do_enable), + .out (dest_enable) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_DEST_REQ) +) i_sync_status_dest ( + .out_clk (clk), + .out_resetn (1'b1), + .in (dest_enabled), + .out (enabled_dest) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_REQ_SRC) +) i_sync_control_src ( + .out_clk (src_clk), + .out_resetn (1'b1), + .in (do_enable), + .out (src_enable) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_REQ_SRC) +) i_sync_status_src ( + .out_clk (clk), + .out_resetn (1'b1), + .in (src_enabled), + .out (enabled_src) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_resize_dest.v b/src/adi/hdl/library/axi_dmac/axi_dmac_resize_dest.v new file mode 100644 index 00000000..c57b7897 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_resize_dest.v @@ -0,0 +1,115 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_resize_dest #( + parameter DATA_WIDTH_DEST = 64, + parameter DATA_WIDTH_MEM = 64 +) ( + input clk, + input reset, + + input mem_data_valid, + output mem_data_ready, + input [DATA_WIDTH_MEM-1:0] mem_data, + input mem_data_last, + + output dest_data_valid, + input dest_data_ready, + output [DATA_WIDTH_DEST-1:0] dest_data, + output dest_data_last +); + +/* + * Resize the data width between the burst memory and the destination interface + * if necessary. + */ + +generate if (DATA_WIDTH_DEST == DATA_WIDTH_MEM) begin + assign dest_data_valid = mem_data_valid; + assign dest_data = mem_data; + assign dest_data_last = mem_data_last; + assign mem_data_ready = dest_data_ready; +end else begin + + localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_DEST; + + reg [$clog2(RATIO)-1:0] count = 'h0; + reg valid = 1'b0; + reg [RATIO-1:0] last = 'h0; + reg [DATA_WIDTH_MEM-1:0] data = 'h0; + + wire last_beat; + + assign last_beat = count == RATIO - 1; + + always @(posedge clk) begin + if (reset == 1'b1) begin + valid <= 1'b0; + end else if (mem_data_valid == 1'b1) begin + valid <= 1'b1; + end else if (last_beat == 1'b1 && dest_data_ready == 1'b1) begin + valid <= 1'b0; + end + end + + always @(posedge clk) begin + if (reset == 1'b1) begin + count <= 'h0; + end else if (dest_data_ready == 1'b1 && dest_data_valid == 1'b1) begin + count <= count + 1; + end + end + + assign mem_data_ready = ~valid | (dest_data_ready & last_beat); + + always @(posedge clk) begin + if (mem_data_ready == 1'b1) begin + data <= mem_data; + last <= {mem_data_last,{RATIO-1{1'b0}}}; + end else if (dest_data_ready == 1'b1) begin + data[DATA_WIDTH_MEM-DATA_WIDTH_DEST-1:0] <= data[DATA_WIDTH_MEM-1:DATA_WIDTH_DEST]; + last[RATIO-2:0] <= last[RATIO-1:1]; + end + end + + assign dest_data_valid = valid; + assign dest_data = data[DATA_WIDTH_DEST-1:0]; + assign dest_data_last = last[0]; + +end endgenerate + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_resize_src.v b/src/adi/hdl/library/axi_dmac/axi_dmac_resize_src.v new file mode 100644 index 00000000..24f696f0 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_resize_src.v @@ -0,0 +1,105 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +/* + * Resize the data width between the source interface and the burst memory + * if necessary. + */ + +`timescale 1ns/100ps + +module axi_dmac_resize_src #( + parameter DATA_WIDTH_SRC = 64, + parameter DATA_WIDTH_MEM = 64 +) ( + input clk, + input reset, + + input src_data_valid, + input [DATA_WIDTH_SRC-1:0] src_data, + input src_data_last, + + output mem_data_valid, + output [DATA_WIDTH_MEM-1:0] mem_data, + output mem_data_last +); + +generate if (DATA_WIDTH_SRC == DATA_WIDTH_MEM) begin + assign mem_data_valid = src_data_valid; + assign mem_data = src_data; + assign mem_data_last = src_data_last; +end else begin + + localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_SRC; + + reg [RATIO-1:0] mask = 'h1; + reg valid = 1'b0; + reg last = 1'b0; + reg [DATA_WIDTH_MEM-1:0] data = 'h0; + + always @(posedge clk) begin + if (reset == 1'b1) begin + valid <= 1'b0; + mask <= 'h1; + end else if (src_data_valid == 1'b1) begin + valid <= mask[RATIO-1] || src_data_last; + if (src_data_last) begin + mask <= 'h1; + end else begin + mask <= {mask[RATIO-2:0],mask[RATIO-1]}; + end + end else begin + valid <= 1'b0; + end + end + + integer i; + + always @(posedge clk) begin + for (i = 0; i < RATIO; i = i+1) begin + if (mask[i] == 1'b1) begin + data[i*DATA_WIDTH_SRC+:DATA_WIDTH_SRC] <= src_data; + end + end + last <= src_data_last; + end + + assign mem_data_valid = valid; + assign mem_data = data; + assign mem_data_last = last; + +end endgenerate + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_response_manager.v b/src/adi/hdl/library/axi_dmac/axi_dmac_response_manager.v new file mode 100644 index 00000000..f55ae933 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_response_manager.v @@ -0,0 +1,279 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_response_manager #( + parameter DMA_DATA_WIDTH_SRC = 64, + parameter DMA_DATA_WIDTH_DEST = 64, + parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DMA_DATA_WIDTH_SRC/8), + parameter ASYNC_CLK_DEST_REQ = 1 +)( + // Interface to destination side + input dest_clk, + input dest_resetn, + + input dest_response_valid, + output dest_response_ready, + input [1:0] dest_response_resp, + input dest_response_partial, + input dest_response_resp_eot, + input [BYTES_PER_BURST_WIDTH-1:0] dest_response_data_burst_length, + + // Interface to processor + input req_clk, + input req_resetn, + + output response_eot, + output reg [BYTES_PER_BURST_WIDTH-1:0] measured_burst_length = 'h0, + output response_partial, + output reg response_valid = 1'b0, + input response_ready, + + // Interface to requester side + input completion_req_valid, + input completion_req_last, + input [1:0] completion_transfer_id +); + +localparam STATE_IDLE = 3'h0; +localparam STATE_ACC = 3'h1; +localparam STATE_WRITE_RESPR = 3'h2; +localparam STATE_ZERO_COMPL = 3'h3; +localparam STATE_WRITE_ZRCMPL = 3'h4; + +reg [2:0] state = STATE_IDLE; +reg [2:0] nx_state; + +localparam DEST_SRC_RATIO = DMA_DATA_WIDTH_DEST/DMA_DATA_WIDTH_SRC; + +localparam DEST_SRC_RATIO_WIDTH = DEST_SRC_RATIO > 64 ? 7 : + DEST_SRC_RATIO > 32 ? 6 : + DEST_SRC_RATIO > 16 ? 5 : + DEST_SRC_RATIO > 8 ? 4 : + DEST_SRC_RATIO > 4 ? 3 : + DEST_SRC_RATIO > 2 ? 2 : + DEST_SRC_RATIO > 1 ? 1 : 0; + +localparam BYTES_PER_BEAT_WIDTH = DEST_SRC_RATIO_WIDTH + BYTES_PER_BEAT_WIDTH_SRC; +localparam BURST_LEN_WIDTH = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH; + +wire do_acc_st; +wire do_compl; +reg req_eot = 1'b0; +reg req_response_partial = 1'b0; +reg [BYTES_PER_BURST_WIDTH-1:0] req_response_dest_data_burst_length = 'h0; + +wire response_dest_valid; +reg response_dest_ready = 1'b1; +wire [1:0] response_dest_resp; +wire response_dest_resp_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] response_dest_data_burst_length; + +wire [BURST_LEN_WIDTH-1:0] burst_lenght; +reg [BURST_LEN_WIDTH-1:0] burst_pointer_end; + +reg [1:0] to_complete_count = 'h0; +reg [1:0] transfer_id = 'h0; +reg completion_req_last_found = 1'b0; + +util_axis_fifo #( + .DATA_WIDTH(BYTES_PER_BURST_WIDTH+1+1), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_DEST_REQ) +) i_dest_response_fifo ( + .s_axis_aclk(dest_clk), + .s_axis_aresetn(dest_resetn), + .s_axis_valid(dest_response_valid), + .s_axis_ready(dest_response_ready), + .s_axis_empty(), + .s_axis_data({dest_response_data_burst_length, + dest_response_partial, + dest_response_resp_eot}), + .s_axis_room(), + + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), + .m_axis_valid(response_dest_valid), + .m_axis_ready(response_dest_ready), + .m_axis_data({response_dest_data_burst_length, + response_dest_partial, + response_dest_resp_eot}), + .m_axis_level() +); + +always @(posedge req_clk) +begin + if (response_dest_valid & response_dest_ready) begin + req_eot <= response_dest_resp_eot; + req_response_partial <= response_dest_partial; + req_response_dest_data_burst_length <= response_dest_data_burst_length; + end +end + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + response_dest_ready <= 1'b1; + end else begin + response_dest_ready <= (nx_state == STATE_IDLE); + end +end + +assign response_eot = (state == STATE_WRITE_RESPR) ? req_eot : 1'b1; +assign response_partial = (state == STATE_WRITE_RESPR) ? req_response_partial : 1'b0; + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + response_valid <= 1'b0; + end else begin + if (nx_state == STATE_WRITE_RESPR || nx_state == STATE_WRITE_ZRCMPL) begin + response_valid <= 1'b1; + end else if (response_ready == 1'b1) begin + response_valid <= 1'b0; + end + end +end + +// transform the free running pointer from burst memory into burst length +assign burst_lenght = req_response_dest_data_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH] - + burst_pointer_end - 1'b1; + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + burst_pointer_end <= {BURST_LEN_WIDTH{1'b1}}; + end else if (state == STATE_ACC) begin + burst_pointer_end <= req_response_dest_data_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH]; + end +end + +always @(posedge req_clk) +begin + if (state == STATE_ZERO_COMPL) begin + measured_burst_length <= {BYTES_PER_BURST_WIDTH{1'b1}}; + end else if (state == STATE_ACC) begin + measured_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH] <= burst_lenght; + measured_burst_length[BYTES_PER_BEAT_WIDTH-1 : 0] <= + req_response_dest_data_burst_length[BYTES_PER_BEAT_WIDTH-1: 0]; + end +end + +always @(*) begin + nx_state = state; + case (state) + STATE_IDLE: begin + if (response_dest_valid == 1'b1) begin + nx_state = STATE_ACC; + end else if (|to_complete_count) begin + if (transfer_id == completion_transfer_id) + nx_state = STATE_ZERO_COMPL; + end + end + STATE_ACC: begin + nx_state = STATE_WRITE_RESPR; + end + STATE_WRITE_RESPR: begin + if (response_ready == 1'b1) begin + nx_state = STATE_IDLE; + end + end + STATE_ZERO_COMPL: begin + if (|to_complete_count) begin + nx_state = STATE_WRITE_ZRCMPL; + end else begin + if (completion_req_last_found == 1'b1) begin + nx_state = STATE_IDLE; + end + end + end + STATE_WRITE_ZRCMPL:begin + if (response_ready == 1'b1) begin + nx_state = STATE_ZERO_COMPL; + end + end + default: begin + nx_state = STATE_IDLE; + end + endcase +end + +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + state <= STATE_IDLE; + end else begin + state <= nx_state; + end +end + +assign do_compl = (state == STATE_WRITE_ZRCMPL) && response_ready; + +// Once the last completion request from request generator is received +// we can wait for completions from the destination side +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + completion_req_last_found <= 1'b0; + end else if (completion_req_valid) begin + completion_req_last_found <= completion_req_last; + end else if (state ==STATE_ZERO_COMPL && ~(|to_complete_count)) begin + completion_req_last_found <= 1'b0; + end +end + +// Track transfers so we can tell when did the destination completed all its +// transfers +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + transfer_id <= 'h0; + end else if ((state == STATE_ACC && req_eot) || do_compl) begin + transfer_id <= transfer_id + 1; + end +end + +// Count how many transfers we need to complete +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + to_complete_count <= 'h0; + end else if (completion_req_valid & ~do_compl) begin + to_complete_count <= to_complete_count + 1; + end else if (~completion_req_valid & do_compl) begin + to_complete_count <= to_complete_count - 1; + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_dmac_transfer.v b/src/adi/hdl/library/axi_dmac/axi_dmac_transfer.v new file mode 100644 index 00000000..d9afc751 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_dmac_transfer.v @@ -0,0 +1,451 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_dmac_transfer #( + parameter DMA_DATA_WIDTH_SRC = 64, + parameter DMA_DATA_WIDTH_DEST = 64, + parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BEAT_WIDTH_DEST = $clog2(DMA_DATA_WIDTH_DEST/8), + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DMA_DATA_WIDTH_SRC/8), + parameter DMA_TYPE_DEST = 0, + parameter DMA_TYPE_SRC = 2, + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter DMA_2D_TRANSFER = 1, + parameter ASYNC_CLK_REQ_SRC = 1, + parameter ASYNC_CLK_SRC_DEST = 1, + parameter ASYNC_CLK_DEST_REQ = 1, + parameter AXI_SLICE_DEST = 0, + parameter AXI_SLICE_SRC = 0, + parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter FIFO_SIZE = 8, + parameter ID_WIDTH = $clog2(FIFO_SIZE*2), + parameter AXI_LENGTH_WIDTH_SRC = 8, + parameter AXI_LENGTH_WIDTH_DEST = 8, + parameter ENABLE_DIAGNOSTICS_IF = 0 +) ( + input ctrl_clk, + input ctrl_resetn, + + input ctrl_enable, + input ctrl_pause, + + input req_valid, + output req_ready, + + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] req_dest_address, + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] req_src_address, + input [DMA_LENGTH_WIDTH-1:0] req_x_length, + input [DMA_LENGTH_WIDTH-1:0] req_y_length, + input [DMA_LENGTH_WIDTH-1:0] req_dest_stride, + input [DMA_LENGTH_WIDTH-1:0] req_src_stride, + input req_sync_transfer_start, + input req_last, + + output req_eot, + output [BYTES_PER_BURST_WIDTH-1:0] req_measured_burst_length, + output req_response_partial, + output req_response_valid, + input req_response_ready, + + // Master AXI interface + input m_dest_axi_aclk, + input m_dest_axi_aresetn, + input m_src_axi_aclk, + input m_src_axi_aresetn, + + // Write address + output [DMA_AXI_ADDR_WIDTH-1:0] m_axi_awaddr, + output [AXI_LENGTH_WIDTH_DEST-1:0] m_axi_awlen, + output [2:0] m_axi_awsize, + output [1:0] m_axi_awburst, + output [2:0] m_axi_awprot, + output [3:0] m_axi_awcache, + output m_axi_awvalid, + input m_axi_awready, + + // Write data + output [DMA_DATA_WIDTH_DEST-1:0] m_axi_wdata, + output [(DMA_DATA_WIDTH_DEST/8)-1:0] m_axi_wstrb, + input m_axi_wready, + output m_axi_wvalid, + output m_axi_wlast, + + // Write response + input m_axi_bvalid, + input [1:0] m_axi_bresp, + output m_axi_bready, + + // Read address + input m_axi_arready, + output m_axi_arvalid, + output [DMA_AXI_ADDR_WIDTH-1:0] m_axi_araddr, + output [AXI_LENGTH_WIDTH_SRC-1:0] m_axi_arlen, + output [2:0] m_axi_arsize, + output [1:0] m_axi_arburst, + output [2:0] m_axi_arprot, + output [3:0] m_axi_arcache, + + // Read data and response + input [DMA_DATA_WIDTH_SRC-1:0] m_axi_rdata, + input m_axi_rlast, + output m_axi_rready, + input m_axi_rvalid, + input [1:0] m_axi_rresp, + + // Slave streaming AXI interface + input s_axis_aclk, + output s_axis_ready, + input s_axis_valid, + input [DMA_DATA_WIDTH_SRC-1:0] s_axis_data, + input [0:0] s_axis_user, + input s_axis_last, + output s_axis_xfer_req, + + // Master streaming AXI interface + input m_axis_aclk, + input m_axis_ready, + output m_axis_valid, + output [DMA_DATA_WIDTH_DEST-1:0] m_axis_data, + output m_axis_last, + output m_axis_xfer_req, + + // Input FIFO interface + input fifo_wr_clk, + input fifo_wr_en, + input [DMA_DATA_WIDTH_SRC-1:0] fifo_wr_din, + output fifo_wr_overflow, + input fifo_wr_sync, + output fifo_wr_xfer_req, + + // Input FIFO interface + input fifo_rd_clk, + input fifo_rd_en, + output fifo_rd_valid, + output [DMA_DATA_WIDTH_DEST-1:0] fifo_rd_dout, + output fifo_rd_underflow, + output fifo_rd_xfer_req, + + output [ID_WIDTH-1:0] dbg_dest_request_id, + output [ID_WIDTH-1:0] dbg_dest_address_id, + output [ID_WIDTH-1:0] dbg_dest_data_id, + output [ID_WIDTH-1:0] dbg_dest_response_id, + output [ID_WIDTH-1:0] dbg_src_request_id, + output [ID_WIDTH-1:0] dbg_src_address_id, + output [ID_WIDTH-1:0] dbg_src_data_id, + output [ID_WIDTH-1:0] dbg_src_response_id, + output [11:0] dbg_status, + + // Diagnostics interface + output [7:0] dest_diag_level_bursts +); + +wire dma_req_valid; +wire dma_req_ready; +wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] dma_req_dest_address; +wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] dma_req_src_address; +wire [DMA_LENGTH_WIDTH-1:0] dma_req_length; +wire [BYTES_PER_BURST_WIDTH-1:0] dma_req_measured_burst_length; +wire dma_req_eot; +wire dma_response_valid; +wire dma_response_ready; +wire dma_response_partial; +wire dma_req_sync_transfer_start; +wire dma_req_last; + +wire req_clk = ctrl_clk; +wire req_resetn; + +wire req_enable; + +wire dest_clk; +wire dest_ext_resetn; +wire dest_resetn; +wire dest_enable; +wire dest_enabled; + +wire src_clk; +wire src_ext_resetn; +wire src_resetn; +wire src_enable; +wire src_enabled; + +wire req_valid_gated; +wire req_ready_gated; + +wire abort_req; + +axi_dmac_reset_manager #( + .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), + .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), + .ASYNC_CLK_DEST_REQ (ASYNC_CLK_DEST_REQ) +) i_reset_manager ( + .clk (ctrl_clk), + .resetn (ctrl_resetn), + + .ctrl_enable (ctrl_enable), + .ctrl_pause (ctrl_pause), + + .req_resetn (req_resetn), + .req_enable (req_enable), + .req_enabled (req_enable), + + .dest_clk (dest_clk), + .dest_ext_resetn (dest_ext_resetn), + .dest_resetn (dest_resetn), + .dest_enable (dest_enable), + .dest_enabled (dest_enabled), + + .src_clk (src_clk), + .src_ext_resetn (src_ext_resetn), + .src_resetn (src_resetn), + .src_enable (src_enable), + .src_enabled (src_enabled), + + .dbg_status (dbg_status) +); + +/* + * Things become a lot easier if we gate incoming requests in a central place + * before they are propagated downstream. Otherwise we'd need to take special + * care to not accidentally accept requests while the DMA is going through a + * shutdown and reset phase. + */ +assign req_valid_gated = req_enable & req_valid; +assign req_ready = req_enable & req_ready_gated; + +generate if (DMA_2D_TRANSFER == 1) begin + +dmac_2d_transfer #( + .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .DMA_LENGTH_WIDTH (DMA_LENGTH_WIDTH), + .BYTES_PER_BURST_WIDTH (BYTES_PER_BURST_WIDTH), + .BYTES_PER_BEAT_WIDTH_DEST (BYTES_PER_BEAT_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH_SRC (BYTES_PER_BEAT_WIDTH_SRC) +) i_2d_transfer ( + .req_aclk (req_clk), + .req_aresetn (req_resetn), + + .req_eot (req_eot), + .req_measured_burst_length (req_measured_burst_length), + .req_response_partial (req_response_partial), + .req_response_valid (req_response_valid), + .req_response_ready (req_response_ready), + + .req_valid (req_valid_gated), + .req_ready (req_ready_gated), + .req_dest_address (req_dest_address), + .req_src_address (req_src_address), + .req_x_length (req_x_length), + .req_y_length (req_y_length), + .req_dest_stride (req_dest_stride), + .req_src_stride (req_src_stride), + .req_sync_transfer_start (req_sync_transfer_start), + .req_last (req_last), + + .out_abort_req (abort_req), + .out_req_valid (dma_req_valid), + .out_req_ready (dma_req_ready), + .out_req_dest_address (dma_req_dest_address), + .out_req_src_address (dma_req_src_address), + .out_req_length (dma_req_length), + .out_req_sync_transfer_start (dma_req_sync_transfer_start), + .out_req_last (dma_req_last), + .out_eot (dma_req_eot), + .out_measured_burst_length (dma_req_measured_burst_length), + .out_response_partial (dma_response_partial), + .out_response_valid (dma_response_valid), + .out_response_ready (dma_response_ready) + ); + +end else begin + +/* Request */ +assign dma_req_valid = req_valid_gated; +assign req_ready_gated = dma_req_ready; + +assign dma_req_dest_address = req_dest_address; +assign dma_req_src_address = req_src_address; +assign dma_req_length = req_x_length; +assign dma_req_sync_transfer_start = req_sync_transfer_start; +assign dma_req_last = req_last; + +/* Response */ +assign req_eot = dma_req_eot; +assign req_measured_burst_length = dma_req_measured_burst_length; +assign req_response_partial = dma_response_partial; +assign req_response_valid = dma_response_valid; +assign dma_response_ready = req_response_ready; + +end endgenerate + +dmac_request_arb #( + .DMA_DATA_WIDTH_SRC (DMA_DATA_WIDTH_SRC), + .DMA_DATA_WIDTH_DEST (DMA_DATA_WIDTH_DEST), + .DMA_LENGTH_WIDTH (DMA_LENGTH_WIDTH), + .BYTES_PER_BEAT_WIDTH_DEST (BYTES_PER_BEAT_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH_SRC (BYTES_PER_BEAT_WIDTH_SRC), + .DMA_TYPE_DEST (DMA_TYPE_DEST), + .DMA_TYPE_SRC (DMA_TYPE_SRC), + .DMA_AXI_ADDR_WIDTH (DMA_AXI_ADDR_WIDTH), + .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), + .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), + .ASYNC_CLK_DEST_REQ (ASYNC_CLK_DEST_REQ), + .AXI_SLICE_DEST (AXI_SLICE_DEST), + .AXI_SLICE_SRC (AXI_SLICE_SRC), + .MAX_BYTES_PER_BURST (MAX_BYTES_PER_BURST), + .BYTES_PER_BURST_WIDTH (BYTES_PER_BURST_WIDTH), + .FIFO_SIZE (FIFO_SIZE), + .ID_WIDTH (ID_WIDTH), + .AXI_LENGTH_WIDTH_DEST (AXI_LENGTH_WIDTH_DEST), + .AXI_LENGTH_WIDTH_SRC (AXI_LENGTH_WIDTH_SRC), + .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF) +) i_request_arb ( + .req_clk (req_clk), + .req_resetn (req_resetn), + + .req_valid (dma_req_valid), + .req_ready (dma_req_ready), + .req_dest_address (dma_req_dest_address), + .req_src_address (dma_req_src_address), + .req_length (dma_req_length), + .req_xlast (dma_req_last), + .req_sync_transfer_start (dma_req_sync_transfer_start), + + .eot (dma_req_eot), + .measured_burst_length(dma_req_measured_burst_length), + .response_partial (dma_response_partial), + .response_valid (dma_response_valid), + .response_ready (dma_response_ready), + + .abort_req (abort_req), + + .req_enable (req_enable), + + .dest_clk (dest_clk), + .dest_ext_resetn (dest_ext_resetn), + .dest_resetn (dest_resetn), + .dest_enable (dest_enable), + .dest_enabled (dest_enabled), + + .src_clk (src_clk), + .src_ext_resetn (src_ext_resetn), + .src_resetn (src_resetn), + .src_enable (src_enable), + .src_enabled (src_enabled), + + .m_dest_axi_aclk (m_dest_axi_aclk), + .m_dest_axi_aresetn (m_dest_axi_aresetn), + .m_src_axi_aclk (m_src_axi_aclk), + .m_src_axi_aresetn (m_src_axi_aresetn), + + .m_axi_awvalid (m_axi_awvalid), + .m_axi_awready (m_axi_awready), + .m_axi_awaddr (m_axi_awaddr), + .m_axi_awlen (m_axi_awlen), + .m_axi_awsize (m_axi_awsize), + .m_axi_awburst (m_axi_awburst), + .m_axi_awprot (m_axi_awprot), + .m_axi_awcache (m_axi_awcache), + + .m_axi_wvalid (m_axi_wvalid), + .m_axi_wready (m_axi_wready), + .m_axi_wdata (m_axi_wdata), + .m_axi_wstrb (m_axi_wstrb), + .m_axi_wlast (m_axi_wlast), + + .m_axi_bvalid (m_axi_bvalid), + .m_axi_bready (m_axi_bready), + .m_axi_bresp (m_axi_bresp), + + .m_axi_arvalid (m_axi_arvalid), + .m_axi_arready (m_axi_arready), + .m_axi_araddr (m_axi_araddr), + .m_axi_arlen (m_axi_arlen), + .m_axi_arsize (m_axi_arsize), + .m_axi_arburst (m_axi_arburst), + .m_axi_arprot (m_axi_arprot), + .m_axi_arcache (m_axi_arcache), + + .m_axi_rready (m_axi_rready), + .m_axi_rvalid (m_axi_rvalid), + .m_axi_rdata (m_axi_rdata), + .m_axi_rlast (m_axi_rlast), + .m_axi_rresp (m_axi_rresp), + + .s_axis_aclk (s_axis_aclk), + .s_axis_ready (s_axis_ready), + .s_axis_valid (s_axis_valid), + .s_axis_data (s_axis_data), + .s_axis_user (s_axis_user), + .s_axis_last (s_axis_last), + .s_axis_xfer_req (s_axis_xfer_req), + + .m_axis_aclk (m_axis_aclk), + .m_axis_ready (m_axis_ready), + .m_axis_valid (m_axis_valid), + .m_axis_data (m_axis_data), + .m_axis_last (m_axis_last), + .m_axis_xfer_req (m_axis_xfer_req), + + .fifo_wr_clk (fifo_wr_clk), + .fifo_wr_en (fifo_wr_en), + .fifo_wr_din (fifo_wr_din), + .fifo_wr_overflow (fifo_wr_overflow), + .fifo_wr_sync (fifo_wr_sync), + .fifo_wr_xfer_req (fifo_wr_xfer_req), + + .fifo_rd_clk (fifo_rd_clk), + .fifo_rd_en (fifo_rd_en), + .fifo_rd_valid (fifo_rd_valid), + .fifo_rd_dout (fifo_rd_dout), + .fifo_rd_underflow (fifo_rd_underflow), + .fifo_rd_xfer_req (fifo_rd_xfer_req), + + .dbg_dest_request_id (dbg_dest_request_id), + .dbg_dest_address_id (dbg_dest_address_id), + .dbg_dest_data_id (dbg_dest_data_id), + .dbg_dest_response_id (dbg_dest_response_id), + .dbg_src_request_id (dbg_src_request_id), + .dbg_src_address_id (dbg_src_address_id), + .dbg_src_data_id (dbg_src_data_id), + .dbg_src_response_id (dbg_src_response_id), + + .dest_diag_level_bursts(dest_diag_level_bursts) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/axi_register_slice.v b/src/adi/hdl/library/axi_dmac/axi_register_slice.v new file mode 100644 index 00000000..e2eea500 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/axi_register_slice.v @@ -0,0 +1,139 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_register_slice #( + + parameter DATA_WIDTH = 32, + parameter FORWARD_REGISTERED = 0, + parameter BACKWARD_REGISTERED = 0)( + + input clk, + input resetn, + + input s_axi_valid, + output s_axi_ready, + input [DATA_WIDTH-1:0] s_axi_data, + + output m_axi_valid, + input m_axi_ready, + output [DATA_WIDTH-1:0] m_axi_data +); + +/* + s_axi_data -> bwd_data -> fwd_data(1) -> m_axi_data + s_axi_valid -> bwd_valid -> fwd_valid(1) -> m_axi_valid + s_axi_ready <- bwd_ready(2) <- fwd_ready <- m_axi_ready + + (1) FORWARD_REGISTERED inserts a set of FF before m_axi_data and m_axi_valid + (2) BACKWARD_REGISTERED insters a FF before s_axi_ready +*/ + +wire [DATA_WIDTH-1:0] bwd_data_s; +wire bwd_valid_s; +wire bwd_ready_s; +wire [DATA_WIDTH-1:0] fwd_data_s; +wire fwd_valid_s; +wire fwd_ready_s; + +generate if (FORWARD_REGISTERED == 1) begin + +reg fwd_valid = 1'b0; +reg [DATA_WIDTH-1:0] fwd_data = 'h00; + +assign fwd_ready_s = ~fwd_valid | m_axi_ready; +assign fwd_valid_s = fwd_valid; +assign fwd_data_s = fwd_data; + +always @(posedge clk) begin + if (~fwd_valid | m_axi_ready) + fwd_data <= bwd_data_s; +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + fwd_valid <= 1'b0; + end else begin + if (bwd_valid_s) + fwd_valid <= 1'b1; + else if (m_axi_ready) + fwd_valid <= 1'b0; + end +end + +end else begin +assign fwd_data_s = bwd_data_s; +assign fwd_valid_s = bwd_valid_s; +assign fwd_ready_s = m_axi_ready; +end +endgenerate + +generate if (BACKWARD_REGISTERED == 1) begin + +reg bwd_ready = 1'b1; +reg [DATA_WIDTH-1:0] bwd_data = 'h00; + +assign bwd_valid_s = ~bwd_ready | s_axi_valid; +assign bwd_data_s = bwd_ready ? s_axi_data : bwd_data; +assign bwd_ready_s = bwd_ready; + +always @(posedge clk) begin + if (bwd_ready) + bwd_data <= s_axi_data; +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + bwd_ready <= 1'b1; + end else begin + if (fwd_ready_s) + bwd_ready <= 1'b1; + else if (s_axi_valid) + bwd_ready <= 1'b0; + end +end + +end else begin +assign bwd_valid_s = s_axi_valid; +assign bwd_data_s = s_axi_data; +assign bwd_ready_s = fwd_ready_s; +end endgenerate + +assign m_axi_data = fwd_data_s; +assign m_axi_valid = fwd_valid_s; +assign s_axi_ready = bwd_ready_s; + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/bd/bd.tcl b/src/adi/hdl/library/axi_dmac/bd/bd.tcl new file mode 100644 index 00000000..54dc8e76 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/bd/bd.tcl @@ -0,0 +1,161 @@ + +proc init {cellpath otherInfo} { + set ip [get_bd_cells $cellpath] + + bd::mark_propagate_override $ip \ + "ASYNC_CLK_REQ_SRC ASYNC_CLK_SRC_DEST ASYNC_CLK_DEST_REQ" + + bd::mark_propagate_only $ip \ + "DMA_AXI_ADDR_WIDTH" + + # On ZYNQ the core is most likely connected to the AXI3 HP ports so use AXI3 + # as the default. + set family [string tolower [get_property FAMILY [get_property PART [current_project]]]] + if {$family == "zynq"} { + set axi_protocol 1 + } else { + set axi_protocol 0 + } + + foreach dir {SRC DEST} { + # This is a bit of a hack, but we can't change the protocol if the type + # is not AXI MM + set old [get_property "CONFIG.DMA_TYPE_${dir}" $ip] + set_property "CONFIG.DMA_TYPE_${dir}" "0" $ip + set_property "CONFIG.DMA_AXI_PROTOCOL_${dir}" $axi_protocol $ip + set_property "CONFIG.DMA_TYPE_${dir}" $old $ip + } +} + +proc post_config_ip {cellpath otherinfo} { + set ip [get_bd_cells $cellpath] + + # Update AXI interface properties according to configuration + set max_bytes_per_burst [get_property "CONFIG.MAX_BYTES_PER_BURST" $ip] + set fifo_size [get_property "CONFIG.FIFO_SIZE" $ip] + + foreach dir {"SRC" "DEST"} { + set type [get_property "CONFIG.DMA_TYPE_$dir" $ip] + if {$type != 0} { + continue + } + + set axi_protocol [get_property "CONFIG.DMA_AXI_PROTOCOL_$dir" $ip] + set data_width [get_property "CONFIG.DMA_DATA_WIDTH_$dir" $ip] + set max_beats_per_burst [expr {int(ceil($max_bytes_per_burst * 8.0 / $data_width))}] + + if {$axi_protocol == 0} { + set axi_protocol_str "AXI4" + if {$max_beats_per_burst > 256} { + set max_beats_per_burst 256 + } + } else { + set axi_protocol_str "AXI3" + if {$max_beats_per_burst > 16} { + set max_beats_per_burst 16 + } + } + + set intf [get_bd_intf_pins [format "%s/m_%s_axi" $cellpath [string tolower $dir]]] + set_property CONFIG.PROTOCOL $axi_protocol_str $intf + set_property CONFIG.MAX_BURST_LENGTH $max_beats_per_burst $intf + + # The core issues as many requests as the amount of data the FIFO can hold + if {$dir == "SRC"} { + set_property CONFIG.NUM_WRITE_OUTSTANDING 0 $intf + set_property CONFIG.NUM_READ_OUTSTANDING $fifo_size $intf + } else { + set_property CONFIG.NUM_WRITE_OUTSTANDING $fifo_size $intf + set_property CONFIG.NUM_READ_OUTSTANDING 0 $intf + } + } +} + +proc axi_dmac_detect_async_clk { cellpath ip param_name clk_a clk_b } { + set param_src [get_property "CONFIG.$param_name.VALUE_SRC" $ip] + if {[string equal $param_src "USER"]} { + return; + } + + set clk_domain_a [get_property CONFIG.CLK_DOMAIN $clk_a] + set clk_domain_b [get_property CONFIG.CLK_DOMAIN $clk_b] + set clk_freq_a [get_property CONFIG.FREQ_HZ $clk_a] + set clk_freq_b [get_property CONFIG.FREQ_HZ $clk_b] + set clk_phase_a [get_property CONFIG.PHASE $clk_a] + set clk_phase_b [get_property CONFIG.PHASE $clk_b] + + # Only mark it as sync if we can make sure that it is sync, if the + # relationship of the clocks is unknown mark it as async + if {$clk_domain_a != {} && $clk_domain_b != {} && \ + $clk_domain_a == $clk_domain_b && $clk_freq_a == $clk_freq_b && \ + $clk_phase_a == $clk_phase_b} { + set clk_async 0 + } else { + set clk_async 1 + } + + set_property "CONFIG.$param_name" $clk_async $ip + +# if {$clk_async == 0} { +# bd::send_msg -of $cellpath -type INFO -msg_id 1 -text "$clk_a and $clk_b are synchronous" +# } else { +# bd::send_msg -of $cellpath -type INFO -msg_id 1 -text "$clk_a and $clk_b are asynchronous" +# } +} + +proc propagate {cellpath otherinfo} { + set ip [get_bd_cells $cellpath] + set src_type [get_property CONFIG.DMA_TYPE_SRC $ip] + set dest_type [get_property CONFIG.DMA_TYPE_DEST $ip] + + set req_clk [get_bd_pins "$ip/s_axi_aclk"] + + if {$src_type == 2} { + set src_clk [get_bd_pins "$ip/fifo_wr_clk"] + } elseif {$src_type == 1} { + set src_clk [get_bd_pins "$ip/s_axis_aclk"] + } else { + set src_clk [get_bd_pins "$ip/m_src_axi_aclk"] + } + + if {$dest_type == 2} { + set dest_clk [get_bd_pins "$ip/fifo_rd_clk"] + } elseif {$dest_type == 1} { + set dest_clk [get_bd_pins "$ip/m_axis_aclk"] + } else { + set dest_clk [get_bd_pins "$ip/m_dest_axi_aclk"] + } + + axi_dmac_detect_async_clk $cellpath $ip "ASYNC_CLK_REQ_SRC" $req_clk $src_clk + axi_dmac_detect_async_clk $cellpath $ip "ASYNC_CLK_SRC_DEST" $src_clk $dest_clk + axi_dmac_detect_async_clk $cellpath $ip "ASYNC_CLK_DEST_REQ" $dest_clk $req_clk +} + +proc post_propagate {cellpath otherinfo} { + set ip [get_bd_cells $cellpath] + + set addr_width 16 + + foreach dir {"SRC" "DEST"} { + set type [get_property "CONFIG.DMA_TYPE_$dir" $ip] + if {$type != 0} { + continue + } + + set intf [get_bd_intf_pins [format "%s/m_%s_axi" $cellpath [string tolower $dir]]] + set addr_segs [get_bd_addr_segs -of_objects [get_bd_addr_spaces $intf]] + + if {$addr_segs != {}} { + foreach addr_seg $addr_segs { + set range [get_property "range" $addr_seg] + set offset [get_property "offset" $addr_seg] + set addr_width [expr max(int(ceil(log($range - 1 + $offset) / log(2))), $addr_width)] + } + } else { + set addr_width 32 + } + + } + + set_property "CONFIG.DMA_AXI_ADDR_WIDTH" $addr_width $ip +} diff --git a/src/adi/hdl/library/axi_dmac/data_mover.v b/src/adi/hdl/library/axi_dmac/data_mover.v new file mode 100644 index 00000000..6da3444b --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/data_mover.v @@ -0,0 +1,266 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_data_mover #( + + parameter ID_WIDTH = 3, + parameter DATA_WIDTH = 64, + parameter BEATS_PER_BURST_WIDTH = 4, + parameter ALLOW_ABORT = 0) ( + + input clk, + input resetn, + + input [ID_WIDTH-1:0] request_id, + output [ID_WIDTH-1:0] response_id, + input eot, + + output rewind_req_valid, + input rewind_req_ready, + output [ID_WIDTH+3-1:0] rewind_req_data, + + output reg bl_valid = 'b0, + input bl_ready, + output reg [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, + + output block_descr_to_dst, + + output [ID_WIDTH-1:0] source_id, + output source_eot, + + output xfer_req, + + output s_axi_ready, + input s_axi_valid, + input [DATA_WIDTH-1:0] s_axi_data, + input s_axi_last, + input s_axi_sync, + + output m_axi_valid, + output [DATA_WIDTH-1:0] m_axi_data, + output m_axi_last, + output m_axi_partial_burst, + + input req_valid, + output req_ready, + input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length, + input req_sync_transfer_start, + input req_xlast +); + +localparam BEAT_COUNTER_MAX = {BEATS_PER_BURST_WIDTH{1'b1}}; + +`include "inc_id.vh" + +reg [BEATS_PER_BURST_WIDTH-1:0] last_burst_length = 'h00; +reg [BEATS_PER_BURST_WIDTH-1:0] beat_counter = 'h00; +reg [BEATS_PER_BURST_WIDTH-1:0] beat_counter_minus_one = 'h0; +reg [ID_WIDTH-1:0] id = 'h00; +reg [ID_WIDTH-1:0] id_next = 'h00; + +reg pending_burst = 1'b0; +reg active = 1'b0; +reg last_eot = 1'b0; +reg last_non_eot = 1'b0; + +reg needs_sync = 1'b0; +wire has_sync = ~needs_sync | s_axi_sync; + +wire s_axi_sync_valid = has_sync & s_axi_valid; +wire transfer_abort_s; + +wire last_load; +wire last; +wire early_tlast; + +assign xfer_req = active; + +assign response_id = id; + +assign source_id = id; +assign source_eot = eot || early_tlast; + +assign last = eot ? last_eot : last_non_eot; + +assign s_axi_ready = (pending_burst & active) & ~transfer_abort_s; +assign m_axi_valid = s_axi_sync_valid & s_axi_ready; +assign m_axi_data = s_axi_data; +assign m_axi_last = last || early_tlast; +assign m_axi_partial_burst = early_tlast; + +assign block_descr_to_dst = transfer_abort_s; + +generate if (ALLOW_ABORT == 1) begin + wire programmed_last; + + reg transfer_abort = 1'b0; + reg req_xlast_d = 1'b0; + reg [1:0] transfer_id = 2'b0; + + assign programmed_last = (last == 1'b1 && eot == 1'b1 && req_xlast_d == 1'b1); + /* + * A 'last' on the external interface indicates the end of an packet. If such a + * 'last' indicator is observed before the end of the current transfer stop + * accepting data on the external interface until a new descriptor is + * received that is the first segment of a transfer. + */ + always @(posedge clk) begin + if (resetn == 1'b0) begin + transfer_abort <= 1'b0; + end else if (req_valid == 1'b1 && req_ready == 1'b1 && req_xlast_d == 1'b1) begin + transfer_abort <= 1'b0; + end else if (m_axi_valid == 1'b1) begin + if (programmed_last == 1'b1) begin + transfer_abort <= 1'b0; + end else if (s_axi_last == 1'b1) begin + transfer_abort <= 1'b1; + end + end + end + + always @(posedge clk) begin + if (req_ready == 1'b1 && req_valid == 1'b1) begin + req_xlast_d <= req_xlast; + end + end + + assign transfer_abort_s = transfer_abort; + assign early_tlast = (s_axi_ready == 1'b1) && (m_axi_valid == 1'b1) && + (s_axi_last == 1'b1) && (programmed_last == 1'b0); + + assign rewind_req_valid = early_tlast; + assign rewind_req_data = {transfer_id,req_xlast_d,id_next}; + + // The width of the id must fit the number of transfers that can be in flight + // in the burst memory + always @(posedge clk) begin + if (resetn == 1'b0) begin + transfer_id <= 2'b0; + end else if (req_valid == 1'b1 && req_ready == 1'b1) begin + transfer_id <= transfer_id + 1'b1; + end + end + +end else begin + assign transfer_abort_s = 1'b0; + assign early_tlast = 1'b0; + assign rewind_req_valid = 1'b0; + assign rewind_req_data = 'h0; +end endgenerate + +/* + * If req_sync_transfer_start is set all incoming beats will be skipped until + * one has s_axi_sync set. This will be the first beat that is passsed through. + */ +always @(posedge clk) begin + if (req_ready == 1'b1) begin + needs_sync <= req_sync_transfer_start; + end else if (m_axi_valid == 1'b1) begin + needs_sync <= 1'b0; + end +end + +// If we want to support zero delay between transfers we have to assert +// req_ready on the same cycle on which the last load happens. +assign last_load = m_axi_valid && last_eot && eot; +assign req_ready = last_load || ~active || (transfer_abort_s & rewind_req_ready); + +always @(posedge clk) begin + if (req_ready) begin + last_eot <= req_last_burst_length == 'h0; + last_non_eot <= 1'b0; + beat_counter <= 'h1; + end else if (m_axi_valid == 1'b1) begin + last_eot <= beat_counter == last_burst_length; + last_non_eot <= beat_counter == BEAT_COUNTER_MAX; + beat_counter <= beat_counter + 1'b1; + end +end + +always @(posedge clk) begin + if (req_ready) + last_burst_length <= req_last_burst_length; +end + +always @(posedge clk) begin + if (req_ready) begin + beat_counter_minus_one <= 'h0; + end else if (m_axi_valid == 1'b1) begin + beat_counter_minus_one <= beat_counter; + end +end + +always @(posedge clk) begin + if (last_load || early_tlast) begin + bl_valid <= 1'b1; + measured_last_burst_length <= beat_counter_minus_one; + end else if (bl_ready) begin + bl_valid <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + active <= 1'b0; + end else if (req_valid == 1'b1) begin + active <= 1'b1; + end else if (last_load == 1'b1) begin + active <= 1'b0; + end +end + +always @(*) +begin + if (m_axi_valid == 1'b1 && (last == 1'b1 || early_tlast == 1'b1)) + id_next <= inc_id(id); + else + id_next <= id; +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else begin + id <= id_next; + end +end + +always @(posedge clk) begin + pending_burst <= id_next != request_id; +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/dest_axi_mm.v b/src/adi/hdl/library/axi_dmac/dest_axi_mm.v new file mode 100644 index 00000000..7b54c485 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/dest_axi_mm.v @@ -0,0 +1,191 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dest_mm_axi #( + + parameter ID_WIDTH = 3, + parameter DMA_DATA_WIDTH = 64, + parameter DMA_ADDR_WIDTH = 32, + parameter BYTES_PER_BEAT_WIDTH = $clog2(DMA_DATA_WIDTH/8), + parameter BEATS_PER_BURST_WIDTH = 4, + parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = $clog2(MAX_BYTES_PER_BURST), + parameter AXI_LENGTH_WIDTH = 8)( + + input m_axi_aclk, + input m_axi_aresetn, + + input req_valid, + output req_ready, + input [DMA_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH] req_address, + + input bl_valid, + output bl_ready, + input [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, + + input enable, + output enabled, + + output response_valid, + input response_ready, + output [1:0] response_resp, + output response_resp_eot, + output response_resp_partial, + output [BYTES_PER_BURST_WIDTH-1:0] response_data_burst_length, + + input [ID_WIDTH-1:0] request_id, + output [ID_WIDTH-1:0] response_id, + + output [ID_WIDTH-1:0] address_id, + input address_eot, + input response_eot, + + input fifo_valid, + output fifo_ready, + input [DMA_DATA_WIDTH-1:0] fifo_data, + input fifo_last, + + input [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length, + input dest_burst_info_partial, + input [ID_WIDTH-1:0] dest_burst_info_id, + input dest_burst_info_write, + // Write address + input m_axi_awready, + output m_axi_awvalid, + output [DMA_ADDR_WIDTH-1:0] m_axi_awaddr, + output [AXI_LENGTH_WIDTH-1:0] m_axi_awlen, + output [ 2:0] m_axi_awsize, + output [ 1:0] m_axi_awburst, + output [ 2:0] m_axi_awprot, + output [ 3:0] m_axi_awcache, + + // Write data + output [DMA_DATA_WIDTH-1:0] m_axi_wdata, + output [(DMA_DATA_WIDTH/8)-1:0] m_axi_wstrb, + input m_axi_wready, + output m_axi_wvalid, + output m_axi_wlast, + + // Write response + input m_axi_bvalid, + input [ 1:0] m_axi_bresp, + output m_axi_bready +); + +wire address_enabled; + +dmac_address_generator #( + .ID_WIDTH(ID_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH), + .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH), + .DMA_DATA_WIDTH(DMA_DATA_WIDTH), + .LENGTH_WIDTH(AXI_LENGTH_WIDTH), + .DMA_ADDR_WIDTH(DMA_ADDR_WIDTH) +) i_addr_gen ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(enable), + .enabled(address_enabled), + + .id(address_id), + .request_id(request_id), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_address(req_address), + + .bl_valid(bl_valid), + .bl_ready(bl_ready), + .measured_last_burst_length(measured_last_burst_length), + + .eot(address_eot), + + .addr_ready(m_axi_awready), + .addr_valid(m_axi_awvalid), + .addr(m_axi_awaddr), + .len(m_axi_awlen), + .size(m_axi_awsize), + .burst(m_axi_awburst), + .prot(m_axi_awprot), + .cache(m_axi_awcache) +); + +assign m_axi_wvalid = fifo_valid; +assign fifo_ready = m_axi_wready; +assign m_axi_wlast = fifo_last; +assign m_axi_wdata = fifo_data; + +assign m_axi_wstrb = {(DMA_DATA_WIDTH/8){1'b1}}; + +dmac_response_handler #( + .ID_WIDTH(ID_WIDTH) +) i_response_handler ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + .bvalid(m_axi_bvalid), + .bready(m_axi_bready), + .bresp(m_axi_bresp), + + .enable(address_enabled), + .enabled(enabled), + + .id(response_id), + .request_id(address_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_resp(response_resp), + .resp_eot(response_resp_eot) +); + +reg [BYTES_PER_BURST_WIDTH+1-1:0] bl_mem [0:2**(ID_WIDTH)-1]; + +assign {response_resp_partial, + response_data_burst_length} = bl_mem[response_id]; + +always @(posedge m_axi_aclk) begin + if (dest_burst_info_write) begin + bl_mem[dest_burst_info_id] <= {dest_burst_info_partial, + dest_burst_info_length}; + end +end + + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/dest_axi_stream.v b/src/adi/hdl/library/axi_dmac/dest_axi_stream.v new file mode 100644 index 00000000..b377d8e6 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/dest_axi_stream.v @@ -0,0 +1,156 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dest_axi_stream #( + + parameter ID_WIDTH = 3, + parameter S_AXIS_DATA_WIDTH = 64, + parameter BEATS_PER_BURST_WIDTH = 4)( + + input s_axis_aclk, + input s_axis_aresetn, + + input enable, + output enabled, + output xfer_req, + + output [ID_WIDTH-1:0] response_id, + output [ID_WIDTH-1:0] data_id, + input data_eot, + input response_eot, + + input m_axis_ready, + output m_axis_valid, + output [S_AXIS_DATA_WIDTH-1:0] m_axis_data, + output m_axis_last, + + output fifo_ready, + input fifo_valid, + input [S_AXIS_DATA_WIDTH-1:0] fifo_data, + input fifo_last, + + input req_valid, + output req_ready, + input req_xlast, + + output response_valid, + input response_ready, + output response_resp_eot, + output [1:0] response_resp +); + +`include "inc_id.vh" + +reg data_enabled = 1'b0; +reg req_xlast_d = 1'b0; +reg active = 1'b0; + +reg [ID_WIDTH-1:0] id = 'h0; + +/* Last beat of the burst */ +wire fifo_last_beat; +/* Last beat of the segment */ +wire fifo_eot_beat; + +/* fifo_last == 1'b1 implies fifo_valid == 1'b1 */ +assign fifo_last_beat = fifo_ready & fifo_last; +assign fifo_eot_beat = fifo_last_beat & data_eot; + +assign req_ready = fifo_eot_beat | ~active; +assign data_id = id; +assign xfer_req = active; + +assign m_axis_valid = fifo_valid & active; +assign fifo_ready = m_axis_ready & active; +assign m_axis_last = req_xlast_d & fifo_last & data_eot; +assign m_axis_data = fifo_data; + +always @(posedge s_axis_aclk) begin + if (s_axis_aresetn == 1'b0) begin + data_enabled <= 1'b0; + end else if (enable == 1'b1) begin + data_enabled <= 1'b1; + end else if (m_axis_valid == 1'b0 || m_axis_ready == 1'b1) begin + data_enabled <= 1'b0; + end +end + +always @(posedge s_axis_aclk) begin + if (req_ready == 1'b1) begin + req_xlast_d <= req_xlast; + end +end + +always @(posedge s_axis_aclk) begin + if (s_axis_aresetn == 1'b0) begin + active <= 1'b0; + end else if (req_valid == 1'b1) begin + active <= 1'b1; + end else if (fifo_eot_beat == 1'b1) begin + active <= 1'b0; + end +end + +always @(posedge s_axis_aclk) begin + if (s_axis_aresetn == 1'b0) begin + id <= 'h00; + end else if (fifo_last_beat == 1'b1) begin + id <= inc_id(id); + end +end + +dmac_response_generator # ( + .ID_WIDTH(ID_WIDTH) +) i_response_generator ( + .clk(s_axis_aclk), + .resetn(s_axis_aresetn), + + .enable(data_enabled), + .enabled(enabled), + + .request_id(id), + .response_id(response_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_eot(response_resp_eot), + .resp_resp(response_resp) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/dest_fifo_inf.v b/src/adi/hdl/library/axi_dmac/dest_fifo_inf.v new file mode 100644 index 00000000..486c7c3c --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/dest_fifo_inf.v @@ -0,0 +1,144 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dest_fifo_inf #( + + parameter ID_WIDTH = 3, + parameter DATA_WIDTH = 64, + parameter BEATS_PER_BURST_WIDTH = 4)( + + input clk, + input resetn, + + input enable, + output enabled, + + input req_valid, + output req_ready, + + output [ID_WIDTH-1:0] response_id, + output reg [ID_WIDTH-1:0] data_id = 'h0, + input data_eot, + input response_eot, + + input en, + output reg [DATA_WIDTH-1:0] dout, + output reg valid, + output reg underflow, + + output xfer_req, + + output fifo_ready, + input fifo_valid, + input [DATA_WIDTH-1:0] fifo_data, + input fifo_last, + + output response_valid, + input response_ready, + output response_resp_eot, + output [1:0] response_resp +); + +`include "inc_id.vh" + +reg active = 1'b0; + +/* Last beat of the burst */ +wire fifo_last_beat; +/* Last beat of the segment */ +wire fifo_eot_beat; + +assign enabled = enable; +assign fifo_ready = en & (fifo_valid | ~enable); + +/* fifo_last == 1'b1 implies fifo_valid == 1'b1 */ +assign fifo_last_beat = fifo_ready & fifo_last; +assign fifo_eot_beat = fifo_last_beat & data_eot; + +assign req_ready = fifo_eot_beat | ~active; +assign xfer_req = active; + +always @(posedge clk) begin + if (en) begin + dout <= fifo_valid ? fifo_data : {DATA_WIDTH{1'b0}}; + valid <= fifo_valid & enable; + underflow <= ~(fifo_valid & enable); + end else begin + valid <= 1'b0; + underflow <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + data_id <= 'h00; + end else if (fifo_last_beat == 1'b1) begin + data_id <= inc_id(data_id); + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + active <= 1'b0; + end else if (req_valid == 1'b1) begin + active <= 1'b1; + end else if (fifo_eot_beat == 1'b1) begin + active <= 1'b0; + end +end + +dmac_response_generator # ( + .ID_WIDTH(ID_WIDTH) +) i_response_generator ( + .clk(clk), + .resetn(resetn), + + .enable(enable), + .enabled(), + + .request_id(data_id), + .response_id(response_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_eot(response_resp_eot), + .resp_resp(response_resp) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/inc_id.vh b/src/adi/hdl/library/axi_dmac/inc_id.vh new file mode 100644 index 00000000..4213143a --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/inc_id.vh @@ -0,0 +1,67 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// - Neither the name of Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, 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. +// *************************************************************************** +// *************************************************************************** + +function [ID_WIDTH-1:0] g2b; + input [ID_WIDTH-1:0] g; + reg [ID_WIDTH-1:0] b; + integer i; + begin + b[ID_WIDTH-1] = g[ID_WIDTH-1]; + for (i = ID_WIDTH - 2; i >= 0; i = i - 1) + b[i] = b[i + 1] ^ g[i]; + g2b = b; + end +endfunction + +function [ID_WIDTH-1:0] b2g; + input [ID_WIDTH-1:0] b; + reg [ID_WIDTH-1:0] g; + integer i; + begin + g[ID_WIDTH-1] = b[ID_WIDTH-1]; + for (i = ID_WIDTH - 2; i >= 0; i = i -1) + g[i] = b[i + 1] ^ b[i]; + b2g = g; + end +endfunction + +function [ID_WIDTH-1:0] inc_id; +input [ID_WIDTH-1:0] id; +begin + inc_id = b2g(g2b(id) + 1); +end +endfunction diff --git a/src/adi/hdl/library/axi_dmac/request_arb.v b/src/adi/hdl/library/axi_dmac/request_arb.v new file mode 100644 index 00000000..3ae9cf18 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/request_arb.v @@ -0,0 +1,1171 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_request_arb #( + parameter DMA_DATA_WIDTH_SRC = 64, + parameter DMA_DATA_WIDTH_DEST = 64, + parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BEAT_WIDTH_DEST = $clog2(DMA_DATA_WIDTH_DEST/8), + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DMA_DATA_WIDTH_SRC/8), + parameter DMA_TYPE_DEST = 0, + parameter DMA_TYPE_SRC = 2, + parameter DMA_AXI_ADDR_WIDTH = 32, + parameter ASYNC_CLK_REQ_SRC = 1, + parameter ASYNC_CLK_SRC_DEST = 1, + parameter ASYNC_CLK_DEST_REQ = 1, + parameter AXI_SLICE_DEST = 0, + parameter AXI_SLICE_SRC = 0, + parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter FIFO_SIZE = 8, + parameter ID_WIDTH = $clog2(FIFO_SIZE*2), + parameter AXI_LENGTH_WIDTH_SRC = 8, + parameter AXI_LENGTH_WIDTH_DEST = 8, + parameter ENABLE_DIAGNOSTICS_IF = 0)( + + input req_clk, + input req_resetn, + + input req_valid, + output req_ready, + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] req_dest_address, + input [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] req_src_address, + input [DMA_LENGTH_WIDTH-1:0] req_length, + input req_xlast, + input req_sync_transfer_start, + + output eot, + output [BYTES_PER_BURST_WIDTH-1:0] measured_burst_length, + output response_partial, + output response_valid, + input response_ready, + + output abort_req, + + // Master AXI interface + input m_dest_axi_aclk, + input m_dest_axi_aresetn, + input m_src_axi_aclk, + input m_src_axi_aresetn, + + // Write address + output [DMA_AXI_ADDR_WIDTH-1:0] m_axi_awaddr, + output [AXI_LENGTH_WIDTH_DEST-1:0] m_axi_awlen, + output [ 2:0] m_axi_awsize, + output [ 1:0] m_axi_awburst, + output [ 2:0] m_axi_awprot, + output [ 3:0] m_axi_awcache, + output m_axi_awvalid, + input m_axi_awready, + + // Write data + output [DMA_DATA_WIDTH_DEST-1:0] m_axi_wdata, + output [(DMA_DATA_WIDTH_DEST/8)-1:0] m_axi_wstrb, + input m_axi_wready, + output m_axi_wvalid, + output m_axi_wlast, + + // Write response + input m_axi_bvalid, + input [ 1:0] m_axi_bresp, + output m_axi_bready, + + // Read address + input m_axi_arready, + output m_axi_arvalid, + output [DMA_AXI_ADDR_WIDTH-1:0] m_axi_araddr, + output [AXI_LENGTH_WIDTH_SRC-1:0] m_axi_arlen, + output [ 2:0] m_axi_arsize, + output [ 1:0] m_axi_arburst, + output [ 2:0] m_axi_arprot, + output [ 3:0] m_axi_arcache, + + // Read data and response + input [DMA_DATA_WIDTH_SRC-1:0] m_axi_rdata, + output m_axi_rready, + input m_axi_rvalid, + input m_axi_rlast, + input [ 1:0] m_axi_rresp, + + // Slave streaming AXI interface + input s_axis_aclk, + output s_axis_ready, + input s_axis_valid, + input [DMA_DATA_WIDTH_SRC-1:0] s_axis_data, + input s_axis_last, + input [0:0] s_axis_user, + output s_axis_xfer_req, + + // Master streaming AXI interface + input m_axis_aclk, + input m_axis_ready, + output m_axis_valid, + output [DMA_DATA_WIDTH_DEST-1:0] m_axis_data, + output m_axis_last, + output m_axis_xfer_req, + + // Input FIFO interface + input fifo_wr_clk, + input fifo_wr_en, + input [DMA_DATA_WIDTH_SRC-1:0] fifo_wr_din, + output fifo_wr_overflow, + input fifo_wr_sync, + output fifo_wr_xfer_req, + + // Input FIFO interface + input fifo_rd_clk, + input fifo_rd_en, + output fifo_rd_valid, + output [DMA_DATA_WIDTH_DEST-1:0] fifo_rd_dout, + output fifo_rd_underflow, + output fifo_rd_xfer_req, + + output [ID_WIDTH-1:0] dbg_dest_request_id, + output [ID_WIDTH-1:0] dbg_dest_address_id, + output [ID_WIDTH-1:0] dbg_dest_data_id, + output [ID_WIDTH-1:0] dbg_dest_response_id, + output [ID_WIDTH-1:0] dbg_src_request_id, + output [ID_WIDTH-1:0] dbg_src_address_id, + output [ID_WIDTH-1:0] dbg_src_data_id, + output [ID_WIDTH-1:0] dbg_src_response_id, + + input req_enable, + + output dest_clk, + input dest_resetn, + output dest_ext_resetn, + input dest_enable, + output dest_enabled, + + output src_clk, + input src_resetn, + output src_ext_resetn, + input src_enable, + output src_enabled, + + // Diagnostics interface + output [7:0] dest_diag_level_bursts +); + +localparam DMA_TYPE_MM_AXI = 0; +localparam DMA_TYPE_STREAM_AXI = 1; +localparam DMA_TYPE_FIFO = 2; + +localparam DMA_ADDRESS_WIDTH_DEST = DMA_AXI_ADDR_WIDTH - BYTES_PER_BEAT_WIDTH_DEST; +localparam DMA_ADDRESS_WIDTH_SRC = DMA_AXI_ADDR_WIDTH - BYTES_PER_BEAT_WIDTH_SRC; + +// Bytes per burst is the same for both dest and src, but bytes per beat may +// differ, so beats per burst may also differ + +localparam BEATS_PER_BURST_WIDTH_SRC = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_SRC; +localparam BEATS_PER_BURST_WIDTH_DEST = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_DEST; + +localparam BURSTS_PER_TRANSFER_WIDTH = DMA_LENGTH_WIDTH - BYTES_PER_BURST_WIDTH; + + +reg eot_mem_src[0:2**ID_WIDTH-1]; +reg eot_mem_dest[0:2**ID_WIDTH-1]; +wire request_eot; +wire source_eot; + +wire [ID_WIDTH-1:0] request_id; +wire [ID_WIDTH-1:0] source_id; +wire [ID_WIDTH-1:0] response_id; + +wire enabled_src; +wire enabled_dest; + +wire req_gen_valid; +wire req_gen_ready; +wire src_dest_valid; +wire src_dest_ready; +wire req_src_valid; +wire req_src_ready; + +wire dest_req_valid; +wire dest_req_ready; +wire [DMA_ADDRESS_WIDTH_DEST-1:0] dest_req_dest_address; +wire dest_req_xlast; + +wire dest_response_valid; +wire dest_response_ready; +wire [1:0] dest_response_resp; +wire dest_response_resp_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] dest_response_data_burst_length; +wire dest_response_partial; + +wire [ID_WIDTH-1:0] dest_request_id; +wire [ID_WIDTH-1:0] dest_data_request_id; +wire [ID_WIDTH-1:0] dest_data_response_id; +wire [ID_WIDTH-1:0] dest_response_id; + +wire dest_valid; +wire dest_ready; +wire [DMA_DATA_WIDTH_DEST-1:0] dest_data; +wire dest_last; +wire dest_fifo_valid; +wire dest_fifo_ready; +wire [DMA_DATA_WIDTH_DEST-1:0] dest_fifo_data; +wire dest_fifo_last; + +wire src_req_valid; +wire src_req_ready; +wire [DMA_ADDRESS_WIDTH_DEST-1:0] src_req_dest_address; +wire [DMA_ADDRESS_WIDTH_SRC-1:0] src_req_src_address; +wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_req_last_burst_length; +wire src_req_sync_transfer_start; +wire src_req_xlast; + +reg [DMA_ADDRESS_WIDTH_DEST-1:0] src_req_dest_address_cur = 'h0; +reg src_req_xlast_cur = 1'b0; + +/* TODO +wire src_response_valid; +wire src_response_ready; +wire src_response_empty; +wire [1:0] src_response_resp; +*/ + +wire [ID_WIDTH-1:0] src_request_id; +reg [ID_WIDTH-1:0] src_throttled_request_id; +wire [ID_WIDTH-1:0] src_data_request_id; +wire [ID_WIDTH-1:0] src_response_id; + +wire src_valid; +wire [DMA_DATA_WIDTH_SRC-1:0] src_data; +wire src_last; +wire src_partial_burst; +wire block_descr_to_dst; +wire src_fifo_valid; +wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data; +wire src_fifo_last; +wire src_fifo_partial_burst; + +wire src_bl_valid; +wire src_bl_ready; +wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_burst_length; + +wire [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length; +wire dest_burst_info_partial; +wire [ID_WIDTH-1:0] dest_burst_info_id; +wire dest_burst_info_write; + +reg src_dest_valid_hs = 1'b0; +wire src_dest_valid_hs_masked; +wire src_dest_ready_hs; + +wire req_rewind_req_valid; +wire [ID_WIDTH+3-1:0] req_rewind_req_data; + +wire completion_req_valid; +wire completion_req_last; +wire [1:0] completion_transfer_id; + +wire rewind_req_valid; +wire rewind_req_ready; +wire [ID_WIDTH+3-1:0] rewind_req_data; + +reg src_throttler_enabled = 1'b1; +wire src_throttler_enable; +wire rewind_state; + +/* Unused for now +wire response_src_valid; +wire response_src_ready = 1'b1; +wire [1:0] response_src_resp; +*/ + +assign dbg_dest_request_id = dest_request_id; +assign dbg_dest_response_id = dest_response_id; +assign dbg_src_request_id = src_request_id; +assign dbg_src_response_id = src_response_id; + +always @(posedge req_clk) +begin + eot_mem_src[request_id] <= request_eot; +end + +always @(posedge src_clk) +begin + eot_mem_dest[source_id] <= source_eot; +end + + +generate if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin + +wire dest_bl_valid; +wire dest_bl_ready; +wire [BEATS_PER_BURST_WIDTH_DEST-1:0] dest_burst_length; +wire [BEATS_PER_BURST_WIDTH_SRC-1:0] dest_src_burst_length; + +assign dest_clk = m_dest_axi_aclk; +assign dest_ext_resetn = m_dest_axi_aresetn; + +wire [ID_WIDTH-1:0] dest_address_id; +wire dest_address_eot = eot_mem_dest[dest_address_id]; +wire dest_response_eot = eot_mem_dest[dest_response_id]; + +assign dbg_dest_address_id = dest_address_id; +assign dbg_dest_data_id = dest_data_response_id; + +assign dest_data_request_id = dest_address_id; + +dmac_dest_mm_axi #( + .ID_WIDTH(ID_WIDTH), + .DMA_DATA_WIDTH(DMA_DATA_WIDTH_DEST), + .DMA_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST), + .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH_DEST), + .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .AXI_LENGTH_WIDTH(AXI_LENGTH_WIDTH_DEST) +) i_dest_dma_mm ( + .m_axi_aclk(m_dest_axi_aclk), + .m_axi_aresetn(dest_resetn), + + .enable(dest_enable), + .enabled(dest_enabled), + + .req_valid(dest_req_valid), + .req_ready(dest_req_ready), + .req_address(dest_req_dest_address), + + .bl_valid(dest_bl_valid), + .bl_ready(dest_bl_ready), + .measured_last_burst_length(dest_burst_length), + + .response_valid(dest_response_valid), + .response_ready(dest_response_ready), + .response_resp(dest_response_resp), + .response_resp_eot(dest_response_resp_eot), + .response_resp_partial(dest_response_partial), + .response_data_burst_length(dest_response_data_burst_length), + + .request_id(dest_request_id), + .response_id(dest_response_id), + + .address_id(dest_address_id), + + .address_eot(dest_address_eot), + .response_eot(dest_response_eot), + + .fifo_valid(dest_valid), + .fifo_ready(dest_ready), + .fifo_data(dest_data), + .fifo_last(dest_last), + + .dest_burst_info_length(dest_burst_info_length), + .dest_burst_info_partial(dest_burst_info_partial), + .dest_burst_info_id(dest_burst_info_id), + .dest_burst_info_write(dest_burst_info_write), + + .m_axi_awready(m_axi_awready), + .m_axi_awvalid(m_axi_awvalid), + .m_axi_awaddr(m_axi_awaddr), + .m_axi_awlen(m_axi_awlen), + .m_axi_awsize(m_axi_awsize), + .m_axi_awburst(m_axi_awburst), + .m_axi_awprot(m_axi_awprot), + .m_axi_awcache(m_axi_awcache), + .m_axi_wready(m_axi_wready), + .m_axi_wvalid(m_axi_wvalid), + .m_axi_wdata(m_axi_wdata), + .m_axi_wstrb(m_axi_wstrb), + .m_axi_wlast(m_axi_wlast), + + .m_axi_bvalid(m_axi_bvalid), + .m_axi_bresp(m_axi_bresp), + .m_axi_bready(m_axi_bready) +); + +util_axis_fifo #( + .DATA_WIDTH(BEATS_PER_BURST_WIDTH_SRC), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_SRC_DEST) +) i_src_dest_bl_fifo ( + .s_axis_aclk(src_clk), + .s_axis_aresetn(src_resetn), + .s_axis_valid(src_bl_valid), + .s_axis_ready(src_bl_ready), + .s_axis_empty(), + .s_axis_data(src_burst_length), + .s_axis_room(), + + .m_axis_aclk(dest_clk), + .m_axis_aresetn(dest_resetn), + .m_axis_valid(dest_bl_valid), + .m_axis_ready(dest_bl_ready), + .m_axis_data(dest_src_burst_length), + .m_axis_level() +); + +// Adapt burst length from source width to destination width by either +// truncation or completion with ones. +if (BEATS_PER_BURST_WIDTH_SRC == BEATS_PER_BURST_WIDTH_DEST) begin +assign dest_burst_length = dest_src_burst_length; +end + +if (BEATS_PER_BURST_WIDTH_SRC < BEATS_PER_BURST_WIDTH_DEST) begin +assign dest_burst_length = {dest_src_burst_length, + {BEATS_PER_BURST_WIDTH_DEST - BEATS_PER_BURST_WIDTH_SRC{1'b1}}}; +end + +if (BEATS_PER_BURST_WIDTH_SRC > BEATS_PER_BURST_WIDTH_DEST) begin +assign dest_burst_length = dest_src_burst_length[BEATS_PER_BURST_WIDTH_SRC-1 -: BEATS_PER_BURST_WIDTH_DEST]; +end + +end else begin + +assign m_axi_awvalid = 1'b0; +assign m_axi_awaddr = 'h00; +assign m_axi_awlen = 'h00; +assign m_axi_awsize = 'h00; +assign m_axi_awburst = 'h00; +assign m_axi_awprot = 'h00; +assign m_axi_awcache = 'h00; + +assign m_axi_wvalid = 1'b0; +assign m_axi_wdata = 'h00; +assign m_axi_wstrb = 'h00; +assign m_axi_wlast = 1'b0; + +assign m_axi_bready = 1'b0; + +assign src_bl_ready = 1'b1; + +assign dest_response_partial = 1'b0; +assign dest_response_data_burst_length = 'h0; + +end + +if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin + +assign dest_clk = m_axis_aclk; +assign dest_ext_resetn = 1'b1; + +wire [ID_WIDTH-1:0] data_id; + +wire data_eot = eot_mem_dest[data_id]; +wire response_eot = eot_mem_dest[dest_response_id]; + +assign dest_data_request_id = dest_request_id; + +assign dbg_dest_address_id = 'h00; +assign dbg_dest_data_id = data_id; + + +dmac_dest_axi_stream #( + .ID_WIDTH(ID_WIDTH), + .S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_DEST), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST) +) i_dest_dma_stream ( + .s_axis_aclk(m_axis_aclk), + .s_axis_aresetn(dest_resetn), + + .enable(dest_enable), + .enabled(dest_enabled), + + .req_valid(dest_req_valid), + .req_ready(dest_req_ready), + .req_xlast(dest_req_xlast), + + .response_valid(dest_response_valid), + .response_ready(dest_response_ready), + .response_resp(dest_response_resp), + .response_resp_eot(dest_response_resp_eot), + + .response_id(dest_response_id), + .data_id(data_id), + .xfer_req(m_axis_xfer_req), + + .data_eot(data_eot), + .response_eot(response_eot), + + .fifo_valid(dest_valid), + .fifo_ready(dest_ready), + .fifo_data(dest_data), + .fifo_last(dest_last), + + .m_axis_valid(m_axis_valid), + .m_axis_ready(m_axis_ready), + .m_axis_data(m_axis_data), + .m_axis_last(m_axis_last) +); + +end else begin + +assign m_axis_valid = 1'b0; +assign m_axis_last = 1'b0; +assign m_axis_xfer_req = 1'b0; +assign m_axis_data = 'h00; + +end + +if (DMA_TYPE_DEST == DMA_TYPE_FIFO) begin + +assign dest_clk = fifo_rd_clk; +assign dest_ext_resetn = 1'b1; + +wire [ID_WIDTH-1:0] data_id; + +wire data_eot = eot_mem_dest[data_id]; +wire response_eot = eot_mem_dest[dest_response_id]; + +assign dest_data_request_id = dest_request_id; + +assign dbg_dest_address_id = 'h00; +assign dbg_dest_data_id = data_id; + +dmac_dest_fifo_inf #( + .ID_WIDTH(ID_WIDTH), + .DATA_WIDTH(DMA_DATA_WIDTH_DEST), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST) +) i_dest_dma_fifo ( + .clk(fifo_rd_clk), + .resetn(dest_resetn), + + .enable(dest_enable), + .enabled(dest_enabled), + + .req_valid(dest_req_valid), + .req_ready(dest_req_ready), + + .response_valid(dest_response_valid), + .response_ready(dest_response_ready), + .response_resp(dest_response_resp), + .response_resp_eot(dest_response_resp_eot), + + .response_id(dest_response_id), + .data_id(data_id), + + .data_eot(data_eot), + .response_eot(response_eot), + + .fifo_valid(dest_valid), + .fifo_ready(dest_ready), + .fifo_data(dest_data), + .fifo_last(dest_last), + + .en(fifo_rd_en), + .valid(fifo_rd_valid), + .dout(fifo_rd_dout), + .underflow(fifo_rd_underflow), + .xfer_req(fifo_rd_xfer_req) +); + +end else begin + +assign fifo_rd_valid = 1'b0; +assign fifo_rd_dout = 'h0; +assign fifo_rd_underflow = 1'b0; +assign fifo_rd_xfer_req = 1'b0; + +end endgenerate + +generate if (DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin + +wire [ID_WIDTH-1:0] src_data_id; +wire [ID_WIDTH-1:0] src_address_id; +wire src_address_eot = eot_mem_src[src_address_id]; + +assign source_id = src_address_id; +assign source_eot = src_address_eot; + +assign src_clk = m_src_axi_aclk; +assign src_ext_resetn = m_src_axi_aresetn; + +assign dbg_src_address_id = src_address_id; +assign dbg_src_data_id = src_data_id; + +dmac_src_mm_axi #( + .ID_WIDTH(ID_WIDTH), + .DMA_DATA_WIDTH(DMA_DATA_WIDTH_SRC), + .DMA_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC), + .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH_SRC), + .AXI_LENGTH_WIDTH(AXI_LENGTH_WIDTH_SRC) +) i_src_dma_mm ( + .m_axi_aclk(m_src_axi_aclk), + .m_axi_aresetn(src_resetn), + + .enable(src_enable), + .enabled(src_enabled), + + .req_valid(src_req_valid), + .req_ready(src_req_ready), + .req_address(src_req_src_address), + .req_last_burst_length(src_req_last_burst_length), + + .bl_valid(src_bl_valid), + .bl_ready(src_bl_ready), + .measured_last_burst_length(src_burst_length), + +/* TODO + .response_valid(src_response_valid), + .response_ready(src_response_ready), + .response_resp(src_response_resp), +*/ + + .request_id(src_throttled_request_id), + .response_id(src_response_id), + .address_id(src_address_id), + .data_id(src_data_id), + + .address_eot(src_address_eot), + + .fifo_valid(src_valid), + .fifo_data(src_data), + .fifo_last(src_last), + + .m_axi_arready(m_axi_arready), + .m_axi_arvalid(m_axi_arvalid), + .m_axi_araddr(m_axi_araddr), + .m_axi_arlen(m_axi_arlen), + .m_axi_arsize(m_axi_arsize), + .m_axi_arburst(m_axi_arburst), + .m_axi_arprot(m_axi_arprot), + .m_axi_arcache(m_axi_arcache), + + .m_axi_rready(m_axi_rready), + .m_axi_rvalid(m_axi_rvalid), + .m_axi_rdata(m_axi_rdata), + .m_axi_rlast(m_axi_rlast), + .m_axi_rresp(m_axi_rresp) +); + +end else begin + +assign m_axi_arvalid = 1'b0; +assign m_axi_araddr = 'h00; +assign m_axi_arlen = 'h00; +assign m_axi_arsize = 'h00; +assign m_axi_arburst = 'h00; +assign m_axi_arcache = 'h00; +assign m_axi_arprot = 'h00; +assign m_axi_rready = 1'b0; + +end + +if (DMA_TYPE_SRC == DMA_TYPE_STREAM_AXI) begin + +assign src_clk = s_axis_aclk; +assign src_ext_resetn = 1'b1; + +wire src_eot = eot_mem_src[src_response_id]; + +assign dbg_src_address_id = 'h00; +assign dbg_src_data_id = 'h00; + +/* TODO +assign src_response_valid = 1'b0; +assign src_response_resp = 2'b0; +*/ + + +dmac_src_axi_stream #( + .ID_WIDTH(ID_WIDTH), + .S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_SRC), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC) +) i_src_dma_stream ( + .s_axis_aclk(s_axis_aclk), + .s_axis_aresetn(src_resetn), + + .enable(src_enable), + .enabled(src_enabled), + + .req_valid(src_req_valid), + .req_ready(src_req_ready), + .req_last_burst_length(src_req_last_burst_length), + .req_sync_transfer_start(src_req_sync_transfer_start), + .req_xlast(src_req_xlast), + + .request_id(src_throttled_request_id), + .response_id(src_response_id), + + .eot(src_eot), + + .rewind_req_valid(rewind_req_valid), + .rewind_req_ready(rewind_req_ready), + .rewind_req_data(rewind_req_data), + + .bl_valid(src_bl_valid), + .bl_ready(src_bl_ready), + .measured_last_burst_length(src_burst_length), + + .block_descr_to_dst(block_descr_to_dst), + + .source_id(source_id), + .source_eot(source_eot), + + .fifo_valid(src_valid), + .fifo_data(src_data), + .fifo_last(src_last), + .fifo_partial_burst(src_partial_burst), + + .s_axis_valid(s_axis_valid), + .s_axis_ready(s_axis_ready), + .s_axis_data(s_axis_data), + .s_axis_last(s_axis_last), + .s_axis_user(s_axis_user), + .s_axis_xfer_req(s_axis_xfer_req) +); + +util_axis_fifo #( + .DATA_WIDTH(ID_WIDTH + 3), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_REQ_SRC) +) i_rewind_req_fifo ( + .s_axis_aclk(src_clk), + .s_axis_aresetn(src_resetn), + .s_axis_valid(rewind_req_valid), + .s_axis_ready(rewind_req_ready), + .s_axis_empty(), + .s_axis_data(rewind_req_data), + .s_axis_room(), + + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), + .m_axis_valid(req_rewind_req_valid), + .m_axis_ready(1'b1), + .m_axis_data(req_rewind_req_data), + .m_axis_level() +); + +end else begin + +assign s_axis_ready = 1'b0; +assign s_axis_xfer_req = 1'b0; +assign rewind_req_valid = 1'b0; +assign rewind_req_data = 'h0; + +assign req_rewind_req_valid = 'b0; +assign req_rewind_req_data = 'h0; + +assign src_partial_burst = 1'b0; +assign block_descr_to_dst = 1'b0; + +end + +if (DMA_TYPE_SRC == DMA_TYPE_FIFO) begin + +wire src_eot = eot_mem_src[src_response_id]; + +assign source_id = src_response_id; +assign source_eot = src_eot; + +assign src_clk = fifo_wr_clk; +assign src_ext_resetn = 1'b1; + +assign dbg_src_address_id = 'h00; +assign dbg_src_data_id = 'h00; + +/* TODO +assign src_response_valid = 1'b0; +assign src_response_resp = 2'b0; +*/ + +dmac_src_fifo_inf #( + .ID_WIDTH(ID_WIDTH), + .DATA_WIDTH(DMA_DATA_WIDTH_SRC), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC) +) i_src_dma_fifo ( + .clk(fifo_wr_clk), + .resetn(src_resetn), + + .enable(src_enable), + .enabled(src_enabled), + + .req_valid(src_req_valid), + .req_ready(src_req_ready), + .req_last_burst_length(src_req_last_burst_length), + .req_sync_transfer_start(src_req_sync_transfer_start), + + .request_id(src_throttled_request_id), + .response_id(src_response_id), + + .eot(src_eot), + + .bl_valid(src_bl_valid), + .bl_ready(src_bl_ready), + .measured_last_burst_length(src_burst_length), + + .fifo_valid(src_valid), + .fifo_data(src_data), + .fifo_last(src_last), + + .en(fifo_wr_en), + .din(fifo_wr_din), + .overflow(fifo_wr_overflow), + .sync(fifo_wr_sync), + .xfer_req(fifo_wr_xfer_req) +); + +end else begin + +assign fifo_wr_overflow = 1'b0; +assign fifo_wr_xfer_req = 1'b0; + +end endgenerate + +sync_bits #( + .NUM_OF_BITS(ID_WIDTH), + .ASYNC_CLK(ASYNC_CLK_REQ_SRC) +) i_sync_src_request_id ( + .out_clk(src_clk), + .out_resetn(1'b1), + .in(request_id), + .out(src_request_id) +); + +`include "inc_id.vh" + +function compare_id; + input [ID_WIDTH-1:0] a; + input [ID_WIDTH-1:0] b; + begin + compare_id = a[ID_WIDTH-1] == b[ID_WIDTH-1]; + if (ID_WIDTH >= 2) begin + if (a[ID_WIDTH-2] == b[ID_WIDTH-2]) begin + compare_id = 1'b1; + end + end + if (ID_WIDTH >= 3) begin + if (a[ID_WIDTH-3:0] != b[ID_WIDTH-3:0]) begin + compare_id = 1'b1; + end + end + end +endfunction + +sync_event #(.ASYNC_CLK(ASYNC_CLK_REQ_SRC)) sync_rewind ( + .in_clk(req_clk), + .in_event(rewind_state), + .out_clk(src_clk), + .out_event(src_throttler_enable) +); + +always @(posedge src_clk) begin + if (src_resetn == 1'b0) begin + src_throttler_enabled <= 'b1; + end else if (rewind_req_valid) begin + src_throttler_enabled <= 'b0; + end else if (src_throttler_enable) begin + src_throttler_enabled <= 'b1; + end +end + +/* + * Make sure that we do not request more data than what fits into the + * store-and-forward burst memory. + * Throttler must be blocked during rewind since it does not tolerate + * a decrement of the request ID. + */ +always @(posedge src_clk) begin + if (src_resetn == 1'b0) begin + src_throttled_request_id <= 'h00; + end else if (rewind_req_valid) begin + src_throttled_request_id <= rewind_req_data[ID_WIDTH-1:0]; + end else if (src_throttled_request_id != src_request_id && + compare_id(src_throttled_request_id, src_data_request_id) && + src_throttler_enabled) begin + src_throttled_request_id <= inc_id(src_throttled_request_id); + end +end + +sync_bits #( + .NUM_OF_BITS(ID_WIDTH), + .ASYNC_CLK(ASYNC_CLK_DEST_REQ) +) i_sync_req_response_id ( + .out_clk(req_clk), + .out_resetn(1'b1), + .in(dest_response_id), + .out(response_id) +); + +axi_register_slice #( + .DATA_WIDTH(DMA_DATA_WIDTH_SRC + 2), + .FORWARD_REGISTERED(AXI_SLICE_SRC), + .BACKWARD_REGISTERED(0) +) i_src_slice ( + .clk(src_clk), + .resetn(src_resetn), + .s_axi_valid(src_valid), + .s_axi_ready(), + .s_axi_data({src_data,src_last,src_partial_burst}), + .m_axi_valid(src_fifo_valid), + .m_axi_ready(1'b1), /* No backpressure */ + .m_axi_data({src_fifo_data,src_fifo_last,src_fifo_partial_burst}) +); + +axi_dmac_burst_memory #( + .DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC), + .DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST), + .ID_WIDTH(ID_WIDTH), + .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), + .ASYNC_CLK(ASYNC_CLK_SRC_DEST), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF) +) i_store_and_forward ( + .src_clk(src_clk), + .src_reset(~src_resetn), + .src_data_valid(src_fifo_valid), + .src_data(src_fifo_data), + .src_data_last(src_fifo_last), + .src_data_valid_bytes({BYTES_PER_BEAT_WIDTH_SRC{1'b1}}), + .src_data_partial_burst(src_fifo_partial_burst), + + .src_data_request_id(src_data_request_id), + + .dest_clk(dest_clk), + .dest_reset(~dest_resetn), + .dest_data_valid(dest_fifo_valid), + .dest_data_ready(dest_fifo_ready), + .dest_data(dest_fifo_data), + .dest_data_last(dest_fifo_last), + + .dest_burst_info_length(dest_burst_info_length), + .dest_burst_info_partial(dest_burst_info_partial), + .dest_burst_info_id(dest_burst_info_id), + .dest_burst_info_write(dest_burst_info_write), + + .dest_request_id(dest_request_id), + .dest_data_request_id(dest_data_request_id), + .dest_data_response_id(dest_data_response_id), + + .dest_diag_level_bursts(dest_diag_level_bursts) +); + +axi_register_slice #( + .DATA_WIDTH(DMA_DATA_WIDTH_DEST + 1), + .FORWARD_REGISTERED(AXI_SLICE_DEST), + .BACKWARD_REGISTERED(AXI_SLICE_DEST) +) i_dest_slice ( + .clk(dest_clk), + .resetn(dest_resetn), + .s_axi_valid(dest_fifo_valid), + .s_axi_ready(dest_fifo_ready), + .s_axi_data({ + dest_fifo_last, + dest_fifo_data + }), + .m_axi_valid(dest_valid), + .m_axi_ready(dest_ready), + .m_axi_data({ + dest_last, + dest_data + }) +); + +// Don't let the request generator run in advance more than one descriptor +// The descriptor FIFO should not block the start of the request generator +// since it becomes ready earlier. +assign req_gen_valid = req_valid & req_ready; +assign req_src_valid = req_valid & req_ready; +assign req_ready = req_gen_ready & req_src_ready; + +util_axis_fifo #( + .DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + 1), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_SRC_DEST) +) i_dest_req_fifo ( + .s_axis_aclk(src_clk), + .s_axis_aresetn(src_resetn), + .s_axis_valid(src_dest_valid_hs_masked), + .s_axis_ready(src_dest_ready_hs), + .s_axis_empty(), + .s_axis_data({ + src_req_dest_address_cur, + src_req_xlast_cur + }), + .s_axis_room(), + + .m_axis_aclk(dest_clk), + .m_axis_aresetn(dest_resetn), + .m_axis_valid(dest_req_valid), + .m_axis_ready(dest_req_ready), + .m_axis_data({ + dest_req_dest_address, + dest_req_xlast + }), + .m_axis_level() +); + +util_axis_fifo #( + .DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + DMA_ADDRESS_WIDTH_SRC + BEATS_PER_BURST_WIDTH_SRC + 2), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_REQ_SRC) +) i_src_req_fifo ( + .s_axis_aclk(req_clk), + .s_axis_aresetn(req_resetn), + .s_axis_valid(req_src_valid), + .s_axis_ready(req_src_ready), + .s_axis_empty(), + .s_axis_data({ + req_dest_address, + req_src_address, + req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC], + req_sync_transfer_start, + req_xlast + }), + .s_axis_room(), + + .m_axis_aclk(src_clk), + .m_axis_aresetn(src_resetn), + .m_axis_valid(src_req_spltr_valid), + .m_axis_ready(src_req_spltr_ready), + .m_axis_data({ + src_req_dest_address, + src_req_src_address, + src_req_last_burst_length, + src_req_sync_transfer_start, + src_req_xlast + }), + .m_axis_level() +); + +// Save the descriptor in the source clock domain since the submission to +// destination is delayed. +always @(posedge src_clk) begin + if (src_req_valid == 1'b1 && src_req_ready == 1'b1) begin + src_req_dest_address_cur <= src_req_dest_address; + src_req_xlast_cur <= src_req_xlast; + end +end + +always @(posedge src_clk) begin + if (src_resetn == 1'b0) begin + src_dest_valid_hs <= 1'b0; + end else if (src_req_valid == 1'b1 && src_req_ready == 1'b1) begin + src_dest_valid_hs <= 1'b1; + end else if (src_dest_ready_hs == 1'b1) begin + src_dest_valid_hs <= 1'b0; + end +end + +// Forward the descriptor to the destination only after the source decided to +// do so +assign src_dest_valid_hs_masked = src_dest_valid_hs == 1'b1 && block_descr_to_dst == 1'b0; +assign src_req_spltr_ready = src_req_ready && src_dest_ready_hs; +assign src_req_valid = src_req_spltr_valid && src_req_spltr_ready; + + +/* Unused for now +util_axis_fifo #( + .DATA_WIDTH(2), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_REQ_SRC) +) i_src_response_fifo ( + .s_axis_aclk(src_clk), + .s_axis_aresetn(src_resetn), + .s_axis_valid(src_response_valid), + .s_axis_ready(src_response_ready), + .s_axis_empty(src_response_empty), + .s_axis_data(src_response_resp), + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), + .m_axis_valid(response_src_valid), + .m_axis_ready(response_src_ready), + .m_axis_data(response_src_resp) +); +assign src_response_empty = 1'b1; +assign src_response_ready = 1'b1; +*/ + +dmac_request_generator #( + .ID_WIDTH(ID_WIDTH), + .BURSTS_PER_TRANSFER_WIDTH(BURSTS_PER_TRANSFER_WIDTH) +) i_req_gen ( + .clk(req_clk), + .resetn(req_resetn), + + .request_id(request_id), + .response_id(response_id), + + .rewind_req_valid(req_rewind_req_valid), + .rewind_req_data(req_rewind_req_data), + .rewind_state(rewind_state), + + .abort_req(abort_req), + + .completion_req_valid(completion_req_valid), + .completion_req_last(completion_req_last), + .completion_transfer_id(completion_transfer_id), + + .req_valid(req_gen_valid), + .req_ready(req_gen_ready), + .req_burst_count(req_length[DMA_LENGTH_WIDTH-1:BYTES_PER_BURST_WIDTH]), + .req_xlast(req_xlast), + + .enable(req_enable), + + .eot(request_eot) +); + +axi_dmac_response_manager #( + .DMA_DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC), + .DMA_DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .ASYNC_CLK_DEST_REQ(ASYNC_CLK_DEST_REQ) +) i_response_manager( + .dest_clk(dest_clk), + .dest_resetn(dest_resetn), + .dest_response_valid(dest_response_valid), + .dest_response_ready(dest_response_ready), + .dest_response_resp(dest_response_resp), + .dest_response_partial(dest_response_partial), + .dest_response_resp_eot(dest_response_resp_eot), + .dest_response_data_burst_length(dest_response_data_burst_length), + + .req_clk(req_clk), + .req_resetn(req_resetn), + .response_eot(eot), + .measured_burst_length(measured_burst_length), + .response_partial(response_partial), + .response_valid(response_valid), + .response_ready(response_ready), + + .completion_req_valid(completion_req_valid), + .completion_req_last(completion_req_last), + .completion_transfer_id(completion_transfer_id) + +); + + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/request_generator.v b/src/adi/hdl/library/axi_dmac/request_generator.v new file mode 100644 index 00000000..75bd7774 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/request_generator.v @@ -0,0 +1,255 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_request_generator #( + + parameter ID_WIDTH = 3, + parameter BURSTS_PER_TRANSFER_WIDTH = 17)( + + input clk, + input resetn, + + output [ID_WIDTH-1:0] request_id, + input [ID_WIDTH-1:0] response_id, + + input rewind_req_valid, + input [ID_WIDTH+3-1:0] rewind_req_data, + output rewind_state, + + output abort_req, + + output reg completion_req_valid = 1'b0, + output completion_req_last, + output [1:0] completion_transfer_id, + + input req_valid, + output reg req_ready, + input [BURSTS_PER_TRANSFER_WIDTH-1:0] req_burst_count, + input req_xlast, + + input enable, + + output eot +); + +`include "inc_id.vh" + +localparam STATE_IDLE = 3'h0; +localparam STATE_GEN_ID = 3'h1; +localparam STATE_REWIND_ID = 3'h2; +localparam STATE_CONSUME = 3'h3; +localparam STATE_WAIT_LAST = 3'h4; + +reg [2:0] state = STATE_IDLE; +reg [2:0] nx_state; + +reg [1:0] rew_transfer_id = 1'b0; +reg rew_req_xlast; +reg [ID_WIDTH-1:0] rew_id = 'h0; + +reg cur_transfer_id = 1'b0; +reg cur_req_xlast; + +wire transfer_id_match; +reg nx_completion_req_valid; + +/* + * Here we only need to count the number of bursts, which means we can ignore + * the lower bits of the byte count. The last last burst may not contain the + * maximum number of bytes, but the address_generator and data_mover will take + * care that only the requested ammount of bytes is transfered. + */ + +reg [BURSTS_PER_TRANSFER_WIDTH-1:0] burst_count = 'h00; +reg [BURSTS_PER_TRANSFER_WIDTH-1:0] cur_burst_length = 'h00; +reg [ID_WIDTH-1:0] id; +wire [ID_WIDTH-1:0] id_next = inc_id(id); +wire incr_en; +wire incr_id; + +assign eot = burst_count == 'h00; +assign request_id = id; + +assign incr_en = (response_id != id_next) && (enable == 1'b1); +assign incr_id = (state == STATE_GEN_ID) && (incr_en == 1'b1); + +always @(posedge clk) begin + if (state == STATE_IDLE) begin + burst_count <= req_burst_count; + end else if (state == STATE_REWIND_ID) begin + burst_count <= cur_burst_length; + end else if (incr_id == 1'b1) begin + burst_count <= burst_count - 1'b1; + end +end +always @(posedge clk) begin + if (req_ready == 1'b1 & req_valid == 1'b1) begin + cur_req_xlast <= req_xlast; + cur_burst_length <= req_burst_count; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else if (state == STATE_REWIND_ID) begin + id <= rew_id; + end else if (incr_id == 1'b1) begin + id <= id_next; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + req_ready <= 1'b0; + end else begin + req_ready <= (nx_state == STATE_IDLE || nx_state == STATE_CONSUME); + end +end + +assign transfer_id_match = cur_transfer_id == rew_transfer_id[0]; + +always @(posedge clk) begin + if (resetn == 1'b0) begin + cur_transfer_id <= 1'b0; + end else if (req_valid == 1'b1 && req_ready == 1'b1) begin + cur_transfer_id <= ~cur_transfer_id; + end +end + +/* + * Once rewind request is received we need to stop incrementing the burst ID. + * + * If the current segment matches the segment that was interrupted and + * if it was a last segment we ignore consecutive segments until the last + * segment is received, in other case we can jump to the next segment. + * + * If the current segment is newer than the one got interrupted and the + * interrupted one was a last segment we need to replay the current + * segment with the adjusted burst ID. If the interrupted segment was not last + * we need to consume/ignore all segments until a last segment is received. + * + * Completion requests are generated for every segment that is + * consumed/ignored. These are handled by the response_manager once the + * interrupted segment got transferred to the destination. + */ +always @(*) begin + nx_state = state; + nx_completion_req_valid = 0; + case (state) + STATE_IDLE: begin + if (rewind_req_valid == 1'b1) begin + nx_state = STATE_REWIND_ID; + end else if (req_valid == 1'b1) begin + nx_state = STATE_GEN_ID; + end + end + STATE_GEN_ID: begin + if (rewind_req_valid == 1'b1) begin + nx_state = STATE_REWIND_ID; + end else if (eot == 1'b1 && incr_en == 1'b1) begin + nx_state = STATE_IDLE; + end + end + STATE_REWIND_ID: begin + if (transfer_id_match) begin + if (rew_req_xlast) begin + nx_state = STATE_IDLE; + end else begin + nx_state = STATE_CONSUME; + end + end else begin + if (rew_req_xlast) begin + nx_state = STATE_GEN_ID; + end else if (cur_req_xlast) begin + nx_state = STATE_IDLE; + nx_completion_req_valid = 1; + end else begin + nx_state = STATE_CONSUME; + nx_completion_req_valid = 1; + end + end + end + STATE_CONSUME: begin + if (req_valid) begin + nx_completion_req_valid = 1; + nx_state = STATE_WAIT_LAST; + end + end + STATE_WAIT_LAST:begin + if (cur_req_xlast) begin + nx_state = STATE_IDLE; + end else begin + nx_state = STATE_CONSUME; + end + end + + default: begin + nx_state = STATE_IDLE; + end + endcase +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + state <= STATE_IDLE; + end else begin + state <= nx_state; + end +end + +always @(posedge clk) begin + if (rewind_req_valid == 1'b1) begin + {rew_transfer_id, rew_req_xlast, rew_id} <= rewind_req_data; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + completion_req_valid <= 1'b0; + end else begin + completion_req_valid <= nx_completion_req_valid; + end +end +assign completion_req_last = cur_req_xlast; +assign completion_transfer_id = rew_transfer_id; + +assign rewind_state = (state == STATE_REWIND_ID); + +assign abort_req = (state == STATE_REWIND_ID) && !rew_req_xlast && !cur_req_xlast; + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/resp.vh b/src/adi/hdl/library/axi_dmac/resp.vh new file mode 100644 index 00000000..a3a73835 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/resp.vh @@ -0,0 +1,4 @@ +localparam RESP_OKAY = 2'b00; +localparam RESP_EXOKAY = 2'b01; +localparam RESP_SLVERR = 2'b10; +localparam RESP_DECERR = 2'b11; diff --git a/src/adi/hdl/library/axi_dmac/response_generator.v b/src/adi/hdl/library/axi_dmac/response_generator.v new file mode 100644 index 00000000..4e7e87b7 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/response_generator.v @@ -0,0 +1,86 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_response_generator #( + + parameter ID_WIDTH = 3)( + + input clk, + input resetn, + + input enable, + output reg enabled, + + input [ID_WIDTH-1:0] request_id, + output reg [ID_WIDTH-1:0] response_id, + + input eot, + + output resp_valid, + input resp_ready, + output resp_eot, + output [1:0] resp_resp +); + +`include "inc_id.vh" +`include "resp.vh" + +assign resp_resp = RESP_OKAY; +assign resp_eot = eot; + +assign resp_valid = request_id != response_id && enabled; + +// We have to wait for all responses before we can disable the response handler +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else if (enable == 1'b1) begin + enabled <= 1'b1; + end else if (request_id == response_id) begin + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + response_id <= 'h0; + end else if (resp_valid == 1'b1 && resp_ready == 1'b1) begin + response_id <= inc_id(response_id); + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/response_handler.v b/src/adi/hdl/library/axi_dmac/response_handler.v new file mode 100644 index 00000000..9dec16b7 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/response_handler.v @@ -0,0 +1,93 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_response_handler #( + + parameter ID_WIDTH = 3)( + + input clk, + input resetn, + + input bvalid, + output bready, + input [1:0] bresp, + + output reg [ID_WIDTH-1:0] id, + input [ID_WIDTH-1:0] request_id, + + input enable, + output reg enabled, + + input eot, + + output resp_valid, + input resp_ready, + output resp_eot, + output [1:0] resp_resp +); + +`include "resp.vh" +`include "inc_id.vh" + +assign resp_resp = bresp; +assign resp_eot = eot; + +wire active = id != request_id; + +assign bready = active && resp_ready; +assign resp_valid = active && bvalid; + +// We have to wait for all responses before we can disable the response handler +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else if (enable == 1'b1) begin + enabled <= 1'b1; + end else if (request_id == id) begin + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else if (bready == 1'b1 && bvalid == 1'b1) begin + id <= inc_id(id); + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/splitter.v b/src/adi/hdl/library/axi_dmac/splitter.v new file mode 100644 index 00000000..04f1287d --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/splitter.v @@ -0,0 +1,69 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module splitter #( + + parameter NUM_M = 2)( + + input clk, + input resetn, + + input s_valid, + output s_ready, + + output [NUM_M-1:0] m_valid, + input [NUM_M-1:0] m_ready +); + +reg [NUM_M-1:0] acked; + +assign s_ready = &(m_ready | acked); +assign m_valid = s_valid ? ~acked : {NUM_M{1'b0}}; + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + acked <= {NUM_M{1'b0}}; + end else begin + if (s_valid & s_ready) + acked <= {NUM_M{1'b0}}; + else + acked <= acked | (m_ready & m_valid); + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/src_axi_mm.v b/src/adi/hdl/library/axi_dmac/src_axi_mm.v new file mode 100644 index 00000000..e813a01d --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/src_axi_mm.v @@ -0,0 +1,222 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_src_mm_axi #( + + parameter ID_WIDTH = 3, + parameter DMA_DATA_WIDTH = 64, + parameter DMA_ADDR_WIDTH = 32, + parameter BYTES_PER_BEAT_WIDTH = 3, + parameter BEATS_PER_BURST_WIDTH = 4, + parameter AXI_LENGTH_WIDTH = 8)( + + input m_axi_aclk, + input m_axi_aresetn, + + input req_valid, + output req_ready, + input [DMA_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH] req_address, + input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length, + + input enable, + output reg enabled = 1'b0, + + output bl_valid, + input bl_ready, + output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, +/* + output response_valid, + input response_ready, + output [1:0] response_resp, +*/ + + input [ID_WIDTH-1:0] request_id, + output [ID_WIDTH-1:0] response_id, + + output [ID_WIDTH-1:0] data_id, + output [ID_WIDTH-1:0] address_id, + input address_eot, + + output fifo_valid, + output [DMA_DATA_WIDTH-1:0] fifo_data, + output fifo_last, + + // Read address + input m_axi_arready, + output m_axi_arvalid, + output [DMA_ADDR_WIDTH-1:0] m_axi_araddr, + output [AXI_LENGTH_WIDTH-1:0] m_axi_arlen, + output [ 2:0] m_axi_arsize, + output [ 1:0] m_axi_arburst, + output [ 2:0] m_axi_arprot, + output [ 3:0] m_axi_arcache, + + // Read data and response + input [DMA_DATA_WIDTH-1:0] m_axi_rdata, + output m_axi_rready, + input m_axi_rvalid, + input m_axi_rlast, + input [ 1:0] m_axi_rresp +); + +`include "inc_id.vh" + +reg [ID_WIDTH-1:0] id = 'h00; + +wire address_enabled; +wire req_ready_ag; +wire req_valid_ag; +wire bl_ready_ag; +wire bl_valid_ag; + +assign data_id = id; +assign response_id = id; + +assign measured_last_burst_length = req_last_burst_length; + +splitter #( + .NUM_M(3) +) i_req_splitter ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + .s_valid(req_valid), + .s_ready(req_ready), + .m_valid({ + bl_valid, + bl_valid_ag, + req_valid_ag + }), + .m_ready({ + bl_ready, + bl_ready_ag, + req_ready_ag + }) +); + +dmac_address_generator #( + .ID_WIDTH(ID_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH), + .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH), + .DMA_DATA_WIDTH(DMA_DATA_WIDTH), + .LENGTH_WIDTH(AXI_LENGTH_WIDTH), + .DMA_ADDR_WIDTH(DMA_ADDR_WIDTH) +) i_addr_gen ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(enable), + .enabled(address_enabled), + + .request_id(request_id), + .id(address_id), + + .req_valid(req_valid_ag), + .req_ready(req_ready_ag), + .req_address(req_address), + + .bl_valid(bl_valid_ag), + .bl_ready(bl_ready_ag), + .measured_last_burst_length(req_last_burst_length), + + .eot(address_eot), + + .addr_ready(m_axi_arready), + .addr_valid(m_axi_arvalid), + .addr(m_axi_araddr), + .len(m_axi_arlen), + .size(m_axi_arsize), + .burst(m_axi_arburst), + .prot(m_axi_arprot), + .cache(m_axi_arcache) +); + +assign fifo_valid = m_axi_rvalid; +assign fifo_data = m_axi_rdata; +assign fifo_last = m_axi_rlast; + +/* + * There is a requirement that data_id <= address_id (modulo 2**ID_WIDTH). We + * know that we will never receive data before we have requested it so there is + * an implicit dependency between data_id and address_id and no need to + * explicitly track it. + */ +always @(posedge m_axi_aclk) begin + if (m_axi_aresetn == 1'b0) begin + id <= 'h00; + end else if (m_axi_rvalid == 1'b1 && m_axi_rlast == 1'b1) begin + id <= inc_id(id); + end +end + +/* + * We won't be receiving data before we've requested it and we won't request + * data unless there is room in the store-and-forward memory. + */ +assign m_axi_rready = 1'b1; + +/* + * We need to complete all bursts for which an address has been put onto the + * AXI-MM interface. + */ +always @(posedge m_axi_aclk) begin + if (m_axi_aresetn == 1'b0) begin + enabled <= 1'b0; + end else if (address_enabled == 1'b1) begin + enabled <= 1'b1; + end else if (id == address_id) begin + enabled <= 1'b0; + end +end + +/* TODO +`include "resp.vh" + +assign response_valid = 1'b0; +assign response_resp = RESP_OKAY; + +reg [1:0] rresp; + +always @(posedge m_axi_aclk) +begin + if (m_axi_rvalid && m_axi_rready) begin + if (m_axi_rresp != 2'b0) + rresp <= m_axi_rresp; + end +end +*/ + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/src_axi_stream.v b/src/adi/hdl/library/axi_dmac/src_axi_stream.v new file mode 100644 index 00000000..e9d59c06 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/src_axi_stream.v @@ -0,0 +1,135 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_src_axi_stream #( + + parameter ID_WIDTH = 3, + parameter S_AXIS_DATA_WIDTH = 64, + parameter LENGTH_WIDTH = 24, + parameter BEATS_PER_BURST_WIDTH = 4)( + + input s_axis_aclk, + input s_axis_aresetn, + + input enable, + output enabled, + + input [ID_WIDTH-1:0] request_id, + output [ID_WIDTH-1:0] response_id, + input eot, + + output rewind_req_valid, + input rewind_req_ready, + output [ID_WIDTH+3-1:0] rewind_req_data, + + output bl_valid, + input bl_ready, + output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, + + output block_descr_to_dst, + + output [ID_WIDTH-1:0] source_id, + output source_eot, + + output s_axis_ready, + input s_axis_valid, + input [S_AXIS_DATA_WIDTH-1:0] s_axis_data, + input [0:0] s_axis_user, + input s_axis_last, + output s_axis_xfer_req, + + output fifo_valid, + output [S_AXIS_DATA_WIDTH-1:0] fifo_data, + output fifo_last, + output fifo_partial_burst, + + input req_valid, + output req_ready, + input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length, + input req_sync_transfer_start, + input req_xlast +); + +assign enabled = enable; + +dmac_data_mover # ( + .ID_WIDTH(ID_WIDTH), + .DATA_WIDTH(S_AXIS_DATA_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH), + .ALLOW_ABORT(1) +) i_data_mover ( + .clk(s_axis_aclk), + .resetn(s_axis_aresetn), + + .xfer_req(s_axis_xfer_req), + + .request_id(request_id), + .response_id(response_id), + .eot(eot), + + .rewind_req_valid(rewind_req_valid), + .rewind_req_ready(rewind_req_ready), + .rewind_req_data(rewind_req_data), + + .bl_valid(bl_valid), + .bl_ready(bl_ready), + .measured_last_burst_length(measured_last_burst_length), + + .block_descr_to_dst(block_descr_to_dst), + + .source_id(source_id), + .source_eot(source_eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + .req_sync_transfer_start(req_sync_transfer_start), + .req_xlast(req_xlast), + + .s_axi_valid(s_axis_valid), + .s_axi_ready(s_axis_ready), + .s_axi_data(s_axis_data), + .s_axi_last(s_axis_last), + .s_axi_sync(s_axis_user[0]), + + .m_axi_valid(fifo_valid), + .m_axi_data(fifo_data), + .m_axi_last(fifo_last), + .m_axi_partial_burst(fifo_partial_burst) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/src_fifo_inf.v b/src/adi/hdl/library/axi_dmac/src_fifo_inf.v new file mode 100644 index 00000000..a9e417bb --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/src_fifo_inf.v @@ -0,0 +1,125 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_src_fifo_inf #( + + parameter ID_WIDTH = 3, + parameter DATA_WIDTH = 64, + parameter BEATS_PER_BURST_WIDTH = 4)( + + input clk, + input resetn, + + input enable, + output enabled, + + input [ID_WIDTH-1:0] request_id, + output [ID_WIDTH-1:0] response_id, + input eot, + + output bl_valid, + input bl_ready, + output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length, + + input en, + input [DATA_WIDTH-1:0] din, + output reg overflow, + input sync, + output xfer_req, + + output fifo_valid, + output [DATA_WIDTH-1:0] fifo_data, + output fifo_last, + + input req_valid, + output req_ready, + input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length, + input req_sync_transfer_start +); + +wire ready; +wire valid; + +assign enabled = enable; + +assign valid = en & ready; + +always @(posedge clk) +begin + if (enable) begin + overflow <= en & ~ready; + end else begin + overflow <= en; + end +end + +dmac_data_mover # ( + .ID_WIDTH(ID_WIDTH), + .DATA_WIDTH(DATA_WIDTH), + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH) +) i_data_mover ( + .clk(clk), + .resetn(resetn), + + .xfer_req(xfer_req), + + .request_id(request_id), + .response_id(response_id), + .eot(eot), + + .bl_valid(bl_valid), + .bl_ready(bl_ready), + .measured_last_burst_length(measured_last_burst_length), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + .req_sync_transfer_start(req_sync_transfer_start), + .req_xlast(1'b0), + + .s_axi_ready(ready), + .s_axi_valid(valid), + .s_axi_data(din), + .s_axi_sync(sync), + .s_axi_last(1'b0), + + .m_axi_valid(fifo_valid), + .m_axi_data(fifo_data), + .m_axi_last(fifo_last) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/axi_read_slave.v b/src/adi/hdl/library/axi_dmac/tb/axi_read_slave.v new file mode 100644 index 00000000..281418bc --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/axi_read_slave.v @@ -0,0 +1,99 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_read_slave #( + parameter DATA_WIDTH = 32, + parameter READ_ACCEPTANCE = 4, + parameter MIN_LATENCY = 48, + parameter MAX_LATENCY = 48 +) ( + input clk, + input reset, + + input arvalid, + output arready, + input [31:0] araddr, + input [7:0] arlen, + input [2:0] arsize, + input [1:0] arburst, + input [2:0] arprot, + input [3:0] arcache, + + output rvalid, + input rready, + output [DATA_WIDTH-1:0] rdata, + output [1:0] rresp, + output rlast +); + +reg [DATA_WIDTH-1:0] data = 'h00; + +assign rresp = 2'b00; +//assign rdata = data; + +always @(posedge clk) begin + if (reset == 1'b1) begin + data <= 'h00; + end else if (rvalid == 1'b1 && rready == 1'b1) begin + data <= data + 1'b1; + end +end + +axi_slave #( + .ACCEPTANCE(READ_ACCEPTANCE), + .MIN_LATENCY(MIN_LATENCY), + .MAX_LATENCY(MAX_LATENCY) +) i_axi_slave ( + .clk(clk), + .reset(reset), + + .valid(arvalid), + .ready(arready), + .addr(araddr), + .len(arlen), + .size(arsize), + .burst(arburst), + .prot(arprot), + .cache(arcache), + + .beat_stb(rvalid), + .beat_ack(rvalid & rready), + .beat_last(rlast), + .beat_addr(rdata) +); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/axi_slave.v b/src/adi/hdl/library/axi_dmac/tb/axi_slave.v new file mode 100644 index 00000000..c60b225a --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/axi_slave.v @@ -0,0 +1,112 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_slave #( + parameter ACCEPTANCE = 3, + parameter MIN_LATENCY = 16, + parameter MAX_LATENCY = 32 +) ( + input clk, + input reset, + + input valid, + output ready, + input [31:0] addr, + input [7:0] len, + input [2:0] size, + input [1:0] burst, + input [2:0] prot, + input [3:0] cache, + + output beat_stb, + input beat_ack, + output [31:0] beat_addr, + output beat_last +); + +reg [31:0] timestamp = 'h00; + +always @(posedge clk) begin + if (reset == 1'b1) begin + timestamp <= 'h00; + end else begin + timestamp <= timestamp + 1'b1; + end +end + +reg [32+32+8-1:0] req_fifo[0:15]; +reg [3:0] req_fifo_rd = 'h00; +reg [3:0] req_fifo_wr = 'h00; +wire [3:0] req_fifo_level = req_fifo_wr - req_fifo_rd; + +assign ready = req_fifo_level < ACCEPTANCE; + +always @(posedge clk) begin + if (reset == 1'b1) begin + req_fifo_wr <= 'h00; + end else begin + if (valid == 1'b1 && ready == 1'b1) begin + req_fifo[req_fifo_wr][71:40] <= timestamp + {$random} % (MAX_LATENCY - MIN_LATENCY + 1) + MIN_LATENCY; + req_fifo[req_fifo_wr][39:0] <= {addr,len}; + req_fifo_wr <= req_fifo_wr + 1'b1; + end + end +end + +reg [7:0] beat_counter = 'h00; + +assign beat_stb = req_fifo_level != 0 && timestamp > req_fifo[req_fifo_rd][71:40]; +assign beat_last = beat_stb ? beat_counter == req_fifo[req_fifo_rd][0+:8] : 1'b0; +assign beat_addr = req_fifo[req_fifo_rd][8+:32] + beat_counter * 4; + +always @(posedge clk) begin + if (reset == 1'b1) begin + beat_counter <= 'h00; + req_fifo_rd <= 'h00; + end else begin + if (beat_ack == 1'b1) begin + if (beat_last == 1'b1) begin + beat_counter <= 'h00; + req_fifo_rd <= req_fifo_rd + 1'b1; + end else begin + beat_counter <= beat_counter + 1'b1; + end + end + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/axi_write_slave.v b/src/adi/hdl/library/axi_dmac/tb/axi_write_slave.v new file mode 100644 index 00000000..06de2f18 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/axi_write_slave.v @@ -0,0 +1,130 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_write_slave #( + parameter DATA_WIDTH = 32, + parameter WRITE_ACCEPTANCE = 3 +) ( + input clk, + input reset, + + input awvalid, + output awready, + input [31:0] awaddr, + input [7:0] awlen, + input [2:0] awsize, + input [1:0] awburst, + input [2:0] awprot, + input [3:0] awcache, + + input wvalid, + output wready, + input [DATA_WIDTH-1:0] wdata, + input [DATA_WIDTH/8-1:0] wstrb, + input wlast, + + output reg bvalid, + input bready, + output [1:0] bresp +); + +wire beat_last; + +axi_slave #( + .ACCEPTANCE(WRITE_ACCEPTANCE) +) i_axi_slave ( + .clk(clk), + .reset(reset), + + .valid(awvalid), + .ready(awready), + .addr(awaddr), + .len(awlen), + .size(awsize), + .burst(awburst), + .prot(awprot), + .cache(awcache), + + .beat_stb(wready), + .beat_ack(wvalid & wready), + .beat_last(beat_last) +); + +reg [4:0] resp_count = 'h00; +wire [4:0] resp_count_next; +reg [DATA_WIDTH-1:0] data_cmp = 'h00; +reg failed = 'b0; + +assign bresp = 2'b00; + +wire resp_count_dec = bvalid & bready; +wire resp_count_inc = wvalid & wready & beat_last; +assign resp_count_next = resp_count - resp_count_dec + resp_count_inc; + +always @(posedge clk) begin + if (reset == 1'b1) begin + resp_count <= 'h00; + end else begin + resp_count <= resp_count - resp_count_dec + resp_count_inc; + end +end + +always @(posedge clk) begin + if (reset == 1'b1) begin + bvalid <= 1'b0; + end else if (bvalid == 1'b0 || bready == 1'b1) begin + if (resp_count_next != 'h00) begin + bvalid <= {$random} % 4 == 0; + end else begin + bvalid <= 1'b0; + end + end +end + +always @(posedge clk) begin + if (reset) begin + data_cmp <= 'h00; + failed <= 'b0; + end else if (wvalid & wready) begin + if (data_cmp !== wdata) begin + failed <= 1'b1; + end + data_cmp <= data_cmp + 'h4; + end +end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb b/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb new file mode 100755 index 00000000..6ba47d32 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb @@ -0,0 +1,19 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" axi_read_slave.v axi_slave.v" +SOURCE+=" ../axi_dmac_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../2d_transfer.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../axi_register_slice.v" +SOURCE+=" ../dest_fifo_inf.v" +SOURCE+=" ../axi_dmac_response_manager.v" +SOURCE+=" ../src_axi_mm.v ../address_generator.v ../response_generator.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" +SOURCE+=" ../../util_cdc/sync_event.v" +SOURCE+=" ../../common/ad_mem.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb.v b/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb.v new file mode 100644 index 00000000..d1d0ec6e --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_read_shutdown_tb.v @@ -0,0 +1,162 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dma_read_shutdown_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `include "tb_base.v" + + localparam TRANSFER_ADDR = 32'h80000000; + localparam TRANSFER_LEN = 24'h2ff; + + reg fifo_clk = 1'b0; + + wire awvalid; + wire awready; + wire [31:0] araddr; + wire [7:0] arlen; + wire [2:0] arsize; + wire [1:0] arburst; + wire [2:0] arprot; + wire [3:0] arcache; + + wire rlast; + wire rvalid; + wire rready; + wire [1:0] rresp; + wire [31:0] rdata; + + /* Twice as fast as the AXI clk so we have lots of read requests */ + always @(*) #5 fifo_clk <= ~fifo_clk; + + axi_read_slave #( + .DATA_WIDTH(32) + ) i_read_slave ( + .clk(clk), + .reset(reset), + + .arvalid(arvalid), + .arready(arready), + .araddr(araddr), + .arlen(arlen), + .arsize(arsize), + .arburst(arburst), + .arprot(arprot), + .arcache(arcache), + + .rready(rready), + .rvalid(rvalid), + .rdata(rdata), + .rresp(rresp), + .rlast(rlast) + ); + + wire [11:0] dbg_status; + + reg ctrl_enable = 1'b0; + + initial begin + #1000 + @(posedge clk) ctrl_enable <= 1'b1; + #3000 + @(posedge clk) ctrl_enable <= 1'b0; + end + + always @(posedge clk) begin + /* + * When disabled the DMA should eventually end up in an idle state and all + * requests that were sent out need to be accepted + */ + failed <= ctrl_enable == 1'b0 && ( + dbg_status !== 12'h701 || + i_read_slave.i_axi_slave.req_fifo_level !== 'h00); + end + + axi_dmac_transfer #( + .DMA_TYPE_SRC(0), + .DMA_TYPE_DEST(2), + .DMA_DATA_WIDTH_SRC(32), + .DMA_DATA_WIDTH_DEST(32), + .FIFO_SIZE(8) + ) i_transfer ( + .m_src_axi_aclk (clk), + .m_src_axi_aresetn(resetn), + + .m_axi_arvalid(arvalid), + .m_axi_arready(arready), + .m_axi_araddr(araddr), + .m_axi_arlen(arlen), + .m_axi_arsize(arsize), + .m_axi_arburst(arburst), + .m_axi_arprot(arprot), + .m_axi_arcache(arcache), + + .m_axi_rready(rready), + .m_axi_rvalid(rvalid), + .m_axi_rdata(rdata), + .m_axi_rlast(rlast), + .m_axi_rresp(rresp), + + .ctrl_clk(clk), + .ctrl_resetn(resetn), + + .ctrl_enable(ctrl_enable), + .ctrl_pause(1'b0), + + .req_eot(), + + .req_valid(1'b1), + .req_ready(), + .req_dest_address(TRANSFER_ADDR[31:2]), + .req_src_address(TRANSFER_ADDR[31:2]), + .req_x_length(TRANSFER_LEN), + .req_y_length(24'h00), + .req_dest_stride(24'h00), + .req_src_stride(24'h00), + .req_sync_transfer_start(1'b0), + .req_last(1'b0), + + .fifo_rd_clk(fifo_clk), + .fifo_rd_en(1'b1), + .fifo_rd_valid(), + .fifo_rd_underflow(), + .fifo_rd_dout(), + + .dbg_status(dbg_status) + ); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_read_tb b/src/adi/hdl/library/axi_dmac/tb/dma_read_tb new file mode 100755 index 00000000..7378f36e --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_read_tb @@ -0,0 +1,18 @@ +#!/bin/bash + +SOURCE="dma_read_tb.v" +SOURCE+=" axi_read_slave.v axi_slave.v" +SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../axi_register_slice.v" +SOURCE+=" ../dest_fifo_inf.v" +SOURCE+=" ../axi_dmac_response_manager.v" +SOURCE+=" ../src_axi_mm.v ../address_generator.v ../response_generator.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" +SOURCE+=" ../../util_cdc/sync_event.v" +SOURCE+=" ../../common/ad_mem.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_read_tb.v b/src/adi/hdl/library/axi_dmac/tb/dma_read_tb.v new file mode 100644 index 00000000..18075e78 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_read_tb.v @@ -0,0 +1,177 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dma_read_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `include "tb_base.v" + + localparam TRANSFER_ADDR = 32'h80000000; + localparam TRANSFER_LEN = 24'h203; + + reg req_valid = 1'b1; + wire req_ready; + reg [23:0] req_length = 'h03; + + wire awvalid; + wire awready; + wire [31:0] araddr; + wire [7:0] arlen; + wire [2:0] arsize; + wire [1:0] arburst; + wire [2:0] arprot; + wire [3:0] arcache; + + wire rlast; + wire rvalid; + wire rready; + wire [1:0] rresp; + wire [31:0] rdata; + + always @(posedge clk) begin + if (reset != 1'b1 && req_ready == 1'b1) begin + req_valid <= 1'b1; + req_length <= req_length + 4; + end + end + + axi_read_slave #( + .DATA_WIDTH(32) + ) i_write_slave ( + .clk(clk), + .reset(reset), + + .arvalid(arvalid), + .arready(arready), + .araddr(araddr), + .arlen(arlen), + .arsize(arsize), + .arburst(arburst), + .arprot(arprot), + .arcache(arcache), + + .rready(rready), + .rvalid(rvalid), + .rdata(rdata), + .rresp(rresp), + .rlast(rlast) + ); + + wire fifo_rd_en = 1'b1; + wire fifo_rd_valid; + wire fifo_rd_underflow; + wire [31:0] fifo_rd_dout; + reg [31:0] fifo_rd_dout_cmp = TRANSFER_ADDR; + reg fifo_rd_dout_mismatch = 1'b0; + reg [31:0] fifo_rd_dout_limit = 'h0; + + axi_dmac_transfer #( + .DMA_TYPE_SRC(0), + .DMA_TYPE_DEST(2), + .DMA_DATA_WIDTH_SRC(32), + .DMA_DATA_WIDTH_DEST(32), + .FIFO_SIZE(8) + ) transfer ( + .m_src_axi_aclk(clk), + .m_src_axi_aresetn(resetn), + + .m_axi_arvalid(arvalid), + .m_axi_arready(arready), + .m_axi_araddr(araddr), + .m_axi_arlen(arlen), + .m_axi_arsize(arsize), + .m_axi_arburst(arburst), + .m_axi_arprot(arprot), + .m_axi_arcache(arcache), + + .m_axi_rready(rready), + .m_axi_rvalid(rvalid), + .m_axi_rdata(rdata), + .m_axi_rlast(rlast), + .m_axi_rresp(rresp), + + .ctrl_clk(clk), + .ctrl_resetn(resetn), + + .ctrl_enable(1'b1), + .ctrl_pause(1'b0), + + .req_eot(eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_dest_address(TRANSFER_ADDR[31:2]), + .req_src_address(TRANSFER_ADDR[31:2]), + .req_x_length(req_length), + .req_y_length(24'h00), + .req_dest_stride(24'h00), + .req_src_stride(24'h00), + .req_sync_transfer_start(1'b0), + + .fifo_rd_clk(clk), + .fifo_rd_en(fifo_rd_en), + .fifo_rd_valid(fifo_rd_valid), + .fifo_rd_underflow(fifo_rd_underflow), + .fifo_rd_dout(fifo_rd_dout) + ); + + always @(posedge clk) begin + if (reset == 1'b1) begin + fifo_rd_dout_cmp <= TRANSFER_ADDR; + fifo_rd_dout_mismatch <= 1'b0; + end else begin + fifo_rd_dout_mismatch <= 1'b0; + + if (fifo_rd_valid == 1'b1) begin + if (fifo_rd_dout_cmp < TRANSFER_ADDR + fifo_rd_dout_limit) begin + fifo_rd_dout_cmp <= (fifo_rd_dout_cmp + 'h4); + end else begin + fifo_rd_dout_cmp <= TRANSFER_ADDR; + fifo_rd_dout_limit <= fifo_rd_dout_limit + 'h4; + end + if (fifo_rd_dout_cmp != fifo_rd_dout) begin + fifo_rd_dout_mismatch <= 1'b1; + end + end + end + end + + always @(posedge clk) begin + failed <= failed | fifo_rd_dout_mismatch; + end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb b/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb new file mode 100755 index 00000000..5fdb11f7 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb @@ -0,0 +1,19 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" axi_write_slave.v axi_slave.v" +SOURCE+=" ../axi_dmac_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../2d_transfer.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" +SOURCE+=" ../src_fifo_inf.v" +SOURCE+=" ../axi_dmac_response_manager.v" +SOURCE+=" ../dest_axi_mm.v ../response_handler.v ../address_generator.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" +SOURCE+=" ../../util_cdc/sync_event.v" +SOURCE+=" ../../common/ad_mem.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb.v b/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb.v new file mode 100644 index 00000000..af037908 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_write_shutdown_tb.v @@ -0,0 +1,169 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dma_write_shutdown_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `include "tb_base.v" + + localparam TRANSFER_ADDR = 32'h80000000; + localparam TRANSFER_LEN = 24'h2ff; + + reg fifo_clk = 1'b0; + + wire awvalid; + wire awready; + wire [31:0] awaddr; + wire [7:0] awlen; + wire [2:0] awsize; + wire [1:0] awburst; + wire [2:0] awprot; + wire [3:0] awcache; + + wire wlast; + wire wvalid; + wire wready; + wire [3:0] wstrb; + wire [31:0] wdata; + + wire bready; + wire bvalid; + wire [1:0] bresp; + + wire [11:0] dbg_status; + + /* Twice as fast as the AXI clk so the FIFO fills up */ + always @(*) #5 fifo_clk <= ~fifo_clk; + + axi_write_slave #( + .DATA_WIDTH(32) + ) i_write_slave ( + .clk(clk), + .reset(reset), + + .awvalid(awvalid), + .awready(awready), + .awaddr(awaddr), + .awlen(awlen), + .awsize(awsize), + .awburst(awburst), + .awprot(awprot), + .awcache(awcache), + + .wready(wready), + .wvalid(wvalid), + .wdata(wdata), + .wstrb(wstrb), + .wlast(wlast), + + .bvalid(bvalid), + .bready(bready), + .bresp(bresp) + ); + + reg ctrl_enable = 1'b0; + + initial begin + #1000 + @(posedge clk) ctrl_enable <= 1'b1; + #3000 + @(posedge clk) ctrl_enable <= 1'b0; + end + + always @(posedge clk) begin + failed <= ctrl_enable == 1'b0 && ( + dbg_status !== 12'h701 || + i_write_slave.i_axi_slave.req_fifo_level !== 'h00); + end + + axi_dmac_transfer #( + .DMA_DATA_WIDTH_SRC(32), + .DMA_DATA_WIDTH_DEST(32), + .FIFO_SIZE(8) + ) i_transfer ( + .m_dest_axi_aclk (clk), + .m_dest_axi_aresetn(resetn), + + .m_axi_awvalid(awvalid), + .m_axi_awready(awready), + .m_axi_awaddr(awaddr), + .m_axi_awlen(awlen), + .m_axi_awsize(awsize), + .m_axi_awburst(awburst), + .m_axi_awprot(awprot), + .m_axi_awcache(awcache), + + .m_axi_wready(wready), + .m_axi_wvalid(wvalid), + .m_axi_wdata(wdata), + .m_axi_wstrb(wstrb), + .m_axi_wlast(wlast), + + .m_axi_bvalid(bvalid), + .m_axi_bready(bready), + .m_axi_bresp(bresp), + + .ctrl_clk(clk), + .ctrl_resetn(resetn), + + .ctrl_enable(ctrl_enable), + .ctrl_pause(1'b0), + + .req_eot(), + .req_response_ready(1'b1), + + .req_valid(1'b1), + .req_ready(), + .req_dest_address(TRANSFER_ADDR[31:2]), + .req_src_address(TRANSFER_ADDR[31:2]), + .req_x_length(TRANSFER_LEN), + .req_y_length(24'h00), + .req_dest_stride(24'h00), + .req_src_stride(24'h00), + .req_sync_transfer_start(1'b0), + .req_last(1'b0), + + .fifo_wr_clk(fifo_clk), + .fifo_wr_en(1'b1), + .fifo_wr_din(32'h00), + .fifo_wr_sync(1'b1), + .fifo_wr_xfer_req(), + + .dbg_status(dbg_status) + ); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_write_tb b/src/adi/hdl/library/axi_dmac/tb/dma_write_tb new file mode 100755 index 00000000..8538ac08 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_write_tb @@ -0,0 +1,18 @@ +#!/bin/bash + +SOURCE="dma_write_tb.v" +SOURCE+=" axi_write_slave.v axi_slave.v" +SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" +SOURCE+=" ../src_fifo_inf.v" +SOURCE+=" ../axi_dmac_response_manager.v" +SOURCE+=" ../dest_axi_mm.v ../response_handler.v ../address_generator.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" +SOURCE+=" ../../util_cdc/sync_event.v" +SOURCE+=" ../../common/ad_mem.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/dma_write_tb.v b/src/adi/hdl/library/axi_dmac/tb/dma_write_tb.v new file mode 100644 index 00000000..90164525 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/dma_write_tb.v @@ -0,0 +1,178 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_dma_write_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `include "tb_base.v" + + reg req_valid = 1'b1; + wire req_ready; + reg [23:0] req_length = 'h03; + wire awvalid; + wire awready; + wire [31:0] awaddr; + wire [7:0] awlen; + wire [2:0] awsize; + wire [1:0] awburst; + wire [2:0] awprot; + wire [3:0] awcache; + + wire wlast; + wire wvalid; + wire wready; + wire [3:0] wstrb; + wire [31:0] wdata; + + reg [31:0] fifo_wr_din = 'b0; + reg fifo_wr_rq = 'b0; + wire fifo_wr_xfer_req; + + wire bready; + wire bvalid; + wire [1:0] bresp; + + always @(posedge clk) begin + if (reset != 1'b1 && req_ready == 1'b1) begin + req_valid <= 1'b1; + req_length <= req_length + 'h4; + end + end + + axi_write_slave #( + .DATA_WIDTH(32) + ) i_write_slave ( + .clk(clk), + .reset(reset), + + .awvalid(awvalid), + .awready(awready), + .awaddr(awaddr), + .awlen(awlen), + .awsize(awsize), + .awburst(awburst), + .awprot(awprot), + .awcache(awcache), + + .wready(wready), + .wvalid(wvalid), + .wdata(wdata), + .wstrb(wstrb), + .wlast(wlast), + + .bvalid(bvalid), + .bready(bready), + .bresp(bresp) + ); + + axi_dmac_transfer #( + .DMA_DATA_WIDTH_SRC(32), + .DMA_DATA_WIDTH_DEST(32) + ) i_transfer ( + .m_dest_axi_aclk (clk), + .m_dest_axi_aresetn(resetn), + + .m_axi_awvalid(awvalid), + .m_axi_awready(awready), + .m_axi_awaddr(awaddr), + .m_axi_awlen(awlen), + .m_axi_awsize(awsize), + .m_axi_awburst(awburst), + .m_axi_awprot(awprot), + .m_axi_awcache(awcache), + + .m_axi_wready(wready), + .m_axi_wvalid(wvalid), + .m_axi_wdata(wdata), + .m_axi_wstrb(wstrb), + .m_axi_wlast(wlast), + + .m_axi_bvalid(bvalid), + .m_axi_bready(bready), + .m_axi_bresp(bresp), + + .ctrl_clk(clk), + .ctrl_resetn(resetn), + + .ctrl_enable(1'b1), + .ctrl_pause(1'b0), + + .req_eot(eot), + .req_response_ready(1'b1), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_dest_address(30'h7e09000), + .req_x_length(req_length), + .req_y_length(24'h00), + .req_dest_stride(24'h00), + .req_src_stride(24'h00), + .req_sync_transfer_start(1'b0), + + .fifo_wr_clk(clk), + .fifo_wr_en(fifo_wr_en), + .fifo_wr_din(fifo_wr_din), + .fifo_wr_overflow(fifo_wr_overflow), + .fifo_wr_sync(1'b1), + .fifo_wr_xfer_req(fifo_wr_xfer_req) + ); + + always @(posedge clk) begin + if (reset) begin + fifo_wr_din <= 'b0; + fifo_wr_rq <= 'b0; + end else begin + if (fifo_wr_en) begin + fifo_wr_din <= fifo_wr_din + 'h4; + end + fifo_wr_rq <= (($random % 4) == 0); + end + end + + assign fifo_wr_en = fifo_wr_rq & fifo_wr_xfer_req; + + always @(posedge clk) begin + if (reset) begin + failed <= 'b0; + end else begin + failed <= failed | + i_write_slave.failed | + fifo_wr_overflow; + end + end + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/regmap_tb b/src/adi/hdl/library/axi_dmac/tb/regmap_tb new file mode 100755 index 00000000..b2467157 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/regmap_tb @@ -0,0 +1,10 @@ +#!/bin/bash + +SOURCE="regmap_tb.v" +SOURCE+=" ../axi_dmac_regmap.v ../axi_dmac_regmap_request.v" +SOURCE+=" ../../common/up_axi.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_axis_fifo/address_sync.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/regmap_tb.v b/src/adi/hdl/library/axi_dmac/tb/regmap_tb.v new file mode 100644 index 00000000..1ab42df5 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/regmap_tb.v @@ -0,0 +1,384 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_regmap_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `define TIMEOUT 1000000 + `include "tb_base.v" + + localparam DMA_LENGTH_WIDTH = 24; + localparam DMA_LENGTH_ALIGN = 3; + localparam BYTES_PER_BEAT = 1; + localparam DMA_AXI_ADDR_WIDTH = 32; + + localparam LENGTH_ALIGN = 2; + localparam LENGTH_MASK = {DMA_LENGTH_WIDTH{1'b1}}; + localparam LENGTH_ALIGN_MASK = {LENGTH_ALIGN{1'b1}}; + localparam STRIDE_MASK = {{DMA_LENGTH_WIDTH-BYTES_PER_BEAT{1'b1}},{BYTES_PER_BEAT{1'b0}}}; + localparam ADDR_MASK = {{DMA_AXI_ADDR_WIDTH-BYTES_PER_BEAT{1'b1}},{BYTES_PER_BEAT{1'b0}}}; + + localparam VAL_DBG_SRC_ADDR = 32'h76543210; + localparam VAL_DBG_DEST_ADDR = 32'hfedcba98; + localparam VAL_DBG_STATUS = 8'ha5; + localparam VAL_DBG_IDS0 = 32'h01234567; + localparam VAL_DBG_IDS1 = 32'h89abcdef; + + localparam AW = 12; + localparam NUM_REGS = 'h200; + + wire s_axi_aclk = clk; + wire s_axi_aresetn = ~reset; + + reg s_axi_awvalid = 1'b0; + reg s_axi_wvalid = 1'b0; + reg [AW-1:0] s_axi_awaddr = 'h00; + reg [31:0] s_axi_wdata = 'h00; + wire [1:0] s_axi_bresp; + wire s_axi_awready; + wire s_axi_wready; + wire s_axi_bready = 1'b1; + wire [3:0] s_axi_wstrb = 4'b1111; + wire [2:0] s_axi_awprot = 3'b000; + wire [2:0] s_axi_arprot = 3'b000; + wire [1:0] s_axi_rresp; + wire [31:0] s_axi_rdata; + + task write_reg; + input [31:0] addr; + input [31:0] value; + begin + @(posedge s_axi_aclk) + s_axi_awvalid <= 1'b1; + s_axi_wvalid <= 1'b1; + s_axi_awaddr <= addr; + s_axi_wdata <= value; + @(posedge s_axi_aclk) + while (s_axi_awvalid || s_axi_wvalid) begin + @(posedge s_axi_aclk) + if (s_axi_awready) + s_axi_awvalid <= 1'b0; + if (s_axi_wready) + s_axi_wvalid <= 1'b0; + end + end + endtask + + reg [31:0] expected_reg_mem[0:NUM_REGS-1]; + + reg [AW-1:0] s_axi_araddr = 'h0; + reg s_axi_arvalid = 'h0; + reg s_axi_rready = 'h0; + wire s_axi_arready; + wire s_axi_rvalid; + + task read_reg; + input [31:0] addr; + output [31:0] value; + begin + s_axi_arvalid <= 1'b1; + s_axi_araddr <= addr; + s_axi_rready <= 1'b1; + @(posedge s_axi_aclk) #0; + while (s_axi_arvalid) begin + if (s_axi_arready == 1'b1) begin + s_axi_arvalid <= 1'b0; + end + @(posedge s_axi_aclk) #0; + end + + while (s_axi_rready) begin + if (s_axi_rvalid == 1'b1) begin + value <= s_axi_rdata; + s_axi_rready <= 1'b0; + end + @(posedge s_axi_aclk) #0; + end + end + endtask + + task read_reg_check; + input [31:0] addr; + output match; + reg [31:0] value; + reg [31:0] expected; + input [255:0] message; + begin + read_reg(addr, value); + expected = expected_reg_mem[addr[11:2]]; + match <= value === expected; + if (value !== expected) begin + $display("%0s: Register mismatch for %x. Expected %x, got %x", + message, addr, expected, value); + end + end + endtask + + reg read_match = 1'b1; + + always @(posedge clk) begin + if (read_match == 1'b0) begin + failed <= 1'b1; + end + end + + + task set_reset_reg_value; + input [31:0] addr; + input [31:0] value; + begin + expected_reg_mem[addr[AW-1:2]] <= value; + end + endtask + + task initialize_expected_reg_mem; + integer i; + begin + for (i = 0; i < NUM_REGS; i = i + 1) + expected_reg_mem[i] <= 'h00; + /* Non zero power-on-reset values */ + set_reset_reg_value('h00, 32'h00040161); /* PCORE version register */ + set_reset_reg_value('h0c, 32'h444d4143); /* PCORE magic register */ + set_reset_reg_value('h80, 'h3); /* IRQ mask */ + + set_reset_reg_value('h40c, 'h3); /* Flags */ + set_reset_reg_value('h418, LENGTH_ALIGN_MASK); /* Length alignment */ + + set_reset_reg_value('h434, VAL_DBG_DEST_ADDR); + set_reset_reg_value('h438, VAL_DBG_SRC_ADDR); + set_reset_reg_value('h43c, VAL_DBG_STATUS); + set_reset_reg_value('h440, VAL_DBG_IDS0); + set_reset_reg_value('h444, VAL_DBG_IDS1); + end + endtask + + task check_all_registers; + input [255:0] message; + integer i; + begin + for (i = 0; i < NUM_REGS*4; i = i + 4) begin + read_reg_check(i, read_match, message); + end + end + endtask + + task write_reg_and_update; + input [31:0] addr; + input [31:0] value; + integer i; + begin + write_reg(addr, value); + expected_reg_mem[addr[AW-1:2]] <= value; + end + endtask + + task invert_register; + input [31:0] addr; + reg [31:0] value; + begin + read_reg(addr, value); + write_reg(addr, ~value); + end + endtask + + task invert_all_registers; + integer i; + begin + for (i = 0; i < NUM_REGS*4; i = i + 4) begin + invert_register(i); + end + end + endtask + + reg request_ready = 1'b0; + wire [31:BYTES_PER_BEAT] request_dest_address; + wire [31:BYTES_PER_BEAT] request_src_address; + wire [DMA_LENGTH_WIDTH-1:0] request_x_length; + wire [DMA_LENGTH_WIDTH-1:0] request_y_length; + wire [DMA_LENGTH_WIDTH-1:0] request_dest_stride; + wire [DMA_LENGTH_WIDTH-1:0] request_src_stride; + wire request_last; + + reg response_eot = 1'b0; + + integer i; + initial begin + initialize_expected_reg_mem(); + @(posedge s_axi_aresetn) + check_all_registers("Initial"); + + /* Check scratch */ + write_reg_and_update('h08, 32'h12345678); + check_all_registers("Scratch"); + + /* Check IRQ mask */ + write_reg_and_update('h80, 32'h0); + check_all_registers("IRQ mask"); + + /* Check transfer registers */ + write_reg_and_update('h40c, 'h3); + write_reg_and_update('h410, ADDR_MASK); + write_reg_and_update('h414, ADDR_MASK); + write_reg_and_update('h418, LENGTH_MASK); + write_reg_and_update('h41c, LENGTH_MASK); + write_reg_and_update('h420, STRIDE_MASK); + write_reg_and_update('h424, STRIDE_MASK); + + check_all_registers("Transfer setup 1"); + + /* Check transfer registers */ + write_reg_and_update('h40c, {$random} & 'h3); + write_reg_and_update('h410, {$random} & ADDR_MASK); + write_reg_and_update('h414, {$random} & ADDR_MASK); + write_reg_and_update('h418, {$random} & LENGTH_MASK | LENGTH_ALIGN_MASK); + write_reg_and_update('h41c, {$random} & LENGTH_MASK); + write_reg_and_update('h420, {$random} & STRIDE_MASK); + write_reg_and_update('h424, {$random} & STRIDE_MASK); + + check_all_registers("Transfer setup 2"); + + /* Start transfer */ + write_reg_and_update('h400, 'h01); + write_reg_and_update('h408, 'h01); + + check_all_registers("Transfer submitted"); + + @(posedge clk) request_ready <= 1'b1; + + /* Interrupt pending */ + set_reset_reg_value('h84, 'h01); + set_reset_reg_value('h88, 'h01); + + /* Transfer ID */ + set_reset_reg_value('h404, 'h01); + + /* Tansfer pending */ + set_reset_reg_value('h408, 'h00); + + check_all_registers("Transfer accepted"); + + @(posedge clk) response_eot <= 1'b1; + @(posedge clk) response_eot <= 1'b0; + + /* Interrupt registers */ + set_reset_reg_value('h84, 'h03); + set_reset_reg_value('h88, 'h03); + + /* Transfer done */ + set_reset_reg_value('h428, 'h01); + + /* Active ID */ + set_reset_reg_value('h42c, 'h01); + + check_all_registers("Transfer completed"); + + /* Clear interrupts */ + write_reg('h84, 'h01); + set_reset_reg_value('h84, 'h02); + set_reset_reg_value('h88, 'h02); + + check_all_registers("Clear interrupts 1"); + + write_reg('h84, 'h02); + set_reset_reg_value('h84, 'h00); + set_reset_reg_value('h88, 'h00); + + check_all_registers("Clear interrupts 2"); + + /* Check that reset works for all registers */ + do_trigger_reset(); + initialize_expected_reg_mem(); + check_all_registers("Reset 1"); + invert_all_registers(); + do_trigger_reset(); + check_all_registers("Reset 2"); + end + + axi_dmac_regmap #( + .ID(0), + .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT), + .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), + .DMA_CYCLIC(1), + .HAS_DEST_ADDR(1), + .HAS_SRC_ADDR(1), + .DMA_2D_TRANSFER(1) + ) i_axi ( + .s_axi_aclk(s_axi_aclk), + .s_axi_aresetn(s_axi_aresetn), + .s_axi_awvalid(s_axi_awvalid), + .s_axi_awaddr(s_axi_awaddr), + .s_axi_awready(s_axi_awready), + .s_axi_awprot(s_axi_awprot), + .s_axi_wvalid(s_axi_wvalid), + .s_axi_wdata(s_axi_wdata), + .s_axi_wstrb(s_axi_wstrb), + .s_axi_wready(s_axi_wready), + .s_axi_bvalid(s_axi_bvalid), + .s_axi_bresp(s_axi_bresp), + .s_axi_bready(s_axi_bready), + .s_axi_arvalid(s_axi_arvalid), + .s_axi_araddr(s_axi_araddr), + .s_axi_arready(s_axi_arready), + .s_axi_arprot(s_axi_arprot), + .s_axi_rvalid(s_axi_rvalid), + .s_axi_rready(s_axi_rready), + .s_axi_rresp(s_axi_rresp), + .s_axi_rdata(s_axi_rdata), + + .request_valid(request_valid), + .request_ready(request_ready), + .request_dest_address(request_dest_address), + .request_src_address(request_src_address), + .request_x_length(request_x_length), + .request_y_length(request_y_length), + .request_dest_stride(request_dest_stride), + .request_src_stride(request_src_stride), + .request_last(request_last), + + .response_eot(response_eot), + + .dbg_src_addr(VAL_DBG_SRC_ADDR), + .dbg_dest_addr(VAL_DBG_DEST_ADDR), + .dbg_status(VAL_DBG_STATUS), + .dbg_ids0(VAL_DBG_IDS0), + .dbg_ids1(VAL_DBG_IDS1) + ); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb b/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb new file mode 100755 index 00000000..cd656cdb --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb @@ -0,0 +1,8 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" ../axi_dmac_reset_manager.v" +SOURCE+=" ../../util_cdc/sync_bits.v" + +cd `dirname $0` +source run_tb.sh diff --git a/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb.v b/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb.v new file mode 100644 index 00000000..e113af59 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/reset_manager_tb.v @@ -0,0 +1,121 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module dmac_reset_manager_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `define TIMEOUT 1000000 + `include "tb_base.v" + + + reg clk_a = 1'b0; + reg clk_b = 1'b0; + reg clk_c = 1'b0; + + reg [5:0] resetn_shift = 'h0; + + reg [10:0] counter = 'h00; + + reg ctrl_enable = 1'b0; + reg ctrl_pause = 1'b0; + + always #10 clk_a <= ~clk_a; + always #3 clk_b <= ~clk_b; + always #7 clk_c <= ~clk_c; + + always @(posedge clk_a) begin + counter <= counter + 1'b1; + if (counter == 'h60 || counter == 'h150 || counter == 'h185) begin + ctrl_enable <= 1'b1; + end else if (counter == 'h100 || counter == 'h110 || counter == 'h180) begin + ctrl_enable <= 1'b0; + end + + if (counter == 'h160) begin + ctrl_pause = 1'b1; + end else if (counter == 'h190) begin + ctrl_pause = 1'b0; + end + end + + reg [15:0] req_enabled_shift; + wire req_enable; + wire req_enabled = req_enabled_shift[15]; + + reg [15:0] dest_enabled_shift; + wire dest_enable; + wire dest_enabled = dest_enabled_shift[15]; + + reg [15:0] src_enabled_shift; + wire src_enable; + wire src_enabled = src_enabled_shift[15]; + + + always @(posedge clk_a) begin + req_enabled_shift <= {req_enabled_shift[14:0],req_enable}; + end + + always @(posedge clk_b) begin + dest_enabled_shift <= {dest_enabled_shift[14:0],dest_enable}; + end + + always @(posedge clk_c) begin + src_enabled_shift <= {src_enabled_shift[14:0],src_enable}; + end + + axi_dmac_reset_manager i_reset_manager ( + .clk(clk_a), + .resetn(resetn), + + .ctrl_pause(ctrl_pause), + .ctrl_enable(ctrl_enable), + + .req_enable(req_enable), + .req_enabled(req_enabled), + + .dest_clk(clk_b), + .dest_ext_resetn(1'b0), + .dest_enable(dest_enable), + .dest_enabled(dest_enabled), + + .src_clk(clk_c), + .src_ext_resetn(1'b0), + .src_enable(src_enable), + .src_enabled(src_enabled) + ); + +endmodule diff --git a/src/adi/hdl/library/axi_dmac/tb/run_tb.sh b/src/adi/hdl/library/axi_dmac/tb/run_tb.sh new file mode 100644 index 00000000..ddf9cc40 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/run_tb.sh @@ -0,0 +1,24 @@ +NAME=`basename $0` + +case "$SIMULATOR" in + modelsim) + # ModelSim flow + vlib work + vlog ${SOURCE} || exit 1 + vsim "dmac_"${NAME} -do "add log /* -r; run -a" -gui || exit 1 + ;; + xsim) + # xsim flow + xvlog -log ${NAME}_xvlog.log --sourcelibdir . ${SOURCE} + xelab -log ${NAME}_xelab.log -debug all dmac_${NAME} + xsim work.dmac_${NAME} -R + ;; + *) + #Icarus flow is the default + mkdir -p run + mkdir -p vcd + iverilog -o run/run_${NAME} -I.. ${SOURCE} $1 || exit 1 + cd vcd + ../run/run_${NAME} + ;; +esac diff --git a/src/adi/hdl/library/axi_dmac/tb/tb_base.v b/src/adi/hdl/library/axi_dmac/tb/tb_base.v new file mode 100644 index 00000000..e6dd7ad9 --- /dev/null +++ b/src/adi/hdl/library/axi_dmac/tb/tb_base.v @@ -0,0 +1,76 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + + reg clk = 1'b0; + reg [3:0] reset_shift = 4'b1111; + reg trigger_reset = 1'b0; + wire reset; + wire resetn = ~reset; + + reg failed = 1'b0; + + initial + begin + $dumpfile (VCD_FILE); + $dumpvars; +`ifdef TIMEOUT + #`TIMEOUT +`else + #100000 +`endif + if (failed == 1'b0) + $display("SUCCESS"); + else + $display("FAILED"); + $finish; + end + + always @(*) #10 clk <= ~clk; + always @(posedge clk) begin + if (trigger_reset == 1'b1) begin + reset_shift <= 3'b111; + end else begin + reset_shift <= {reset_shift[2:0],1'b0}; + end + end + + assign reset = reset_shift[3]; + + task do_trigger_reset; + begin + @(posedge clk) trigger_reset <= 1'b1; + @(posedge clk) trigger_reset <= 1'b0; + end + endtask From d8f88cdecd086832fae7a514677dc0b9603beada Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 16:05:18 -0400 Subject: [PATCH 21/30] adi: hdl: Add dependencies needed by axi_dmac --- src/adi/hdl/library/interfaces/Makefile | 52 ++++ .../hdl/library/interfaces/interfaces_ip.tcl | 99 +++++++ src/adi/hdl/library/util_axis_fifo/Makefile | 18 ++ .../hdl/library/util_axis_fifo/address_gray.v | 155 +++++++++++ .../util_axis_fifo/address_gray_pipelined.v | 152 +++++++++++ .../hdl/library/util_axis_fifo/address_sync.v | 109 ++++++++ .../library/util_axis_fifo/util_axis_fifo.v | 243 ++++++++++++++++++ .../util_axis_fifo/util_axis_fifo_ip.tcl | 41 +++ src/adi/hdl/library/util_cdc/Makefile | 15 ++ src/adi/hdl/library/util_cdc/sync_bits.v | 79 ++++++ src/adi/hdl/library/util_cdc/sync_data.v | 97 +++++++ src/adi/hdl/library/util_cdc/sync_event.v | 120 +++++++++ src/adi/hdl/library/util_cdc/sync_gray.v | 115 +++++++++ .../hdl/library/util_cdc/util_cdc_constr.tcl | 58 +++++ src/adi/hdl/library/util_cdc/util_cdc_ip.tcl | 43 ++++ 15 files changed, 1396 insertions(+) create mode 100644 src/adi/hdl/library/interfaces/Makefile create mode 100644 src/adi/hdl/library/interfaces/interfaces_ip.tcl create mode 100644 src/adi/hdl/library/util_axis_fifo/Makefile create mode 100644 src/adi/hdl/library/util_axis_fifo/address_gray.v create mode 100644 src/adi/hdl/library/util_axis_fifo/address_gray_pipelined.v create mode 100644 src/adi/hdl/library/util_axis_fifo/address_sync.v create mode 100644 src/adi/hdl/library/util_axis_fifo/util_axis_fifo.v create mode 100644 src/adi/hdl/library/util_axis_fifo/util_axis_fifo_ip.tcl create mode 100644 src/adi/hdl/library/util_cdc/Makefile create mode 100644 src/adi/hdl/library/util_cdc/sync_bits.v create mode 100644 src/adi/hdl/library/util_cdc/sync_data.v create mode 100644 src/adi/hdl/library/util_cdc/sync_event.v create mode 100644 src/adi/hdl/library/util_cdc/sync_gray.v create mode 100644 src/adi/hdl/library/util_cdc/util_cdc_constr.tcl create mode 100644 src/adi/hdl/library/util_cdc/util_cdc_ip.tcl diff --git a/src/adi/hdl/library/interfaces/Makefile b/src/adi/hdl/library/interfaces/Makefile new file mode 100644 index 00000000..5e69904a --- /dev/null +++ b/src/adi/hdl/library/interfaces/Makefile @@ -0,0 +1,52 @@ +#################################################################################### +#################################################################################### +## Copyright 2011(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### +#################################################################################### + +include ../../quiet.mk + +M_DEPS := interfaces_ip.tcl +M_DEPS += ../scripts/adi_env.tcl +M_DEPS += ../scripts/adi_ip.tcl + +M_VIVADO := vivado -mode batch -source + +M_FLIST := *.log +M_FLIST += *.jou +M_FLIST += if_xcvr_cm.xml +M_FLIST += if_xcvr_cm_rtl.xml +M_FLIST += if_xcvr_ch.xml +M_FLIST += if_xcvr_ch_rtl.xml +M_FLIST += if_gt_qpll.xml +M_FLIST += if_gt_qpll_rtl.xml +M_FLIST += if_gt_pll.xml +M_FLIST += if_gt_pll_rtl.xml +M_FLIST += if_gt_rx.xml +M_FLIST += if_gt_rx_rtl.xml +M_FLIST += if_gt_tx.xml +M_FLIST += if_gt_tx_rtl.xml +M_FLIST += if_gt_rx_ksig.xml +M_FLIST += if_gt_rx_ksig_rtl.xml + + +.PHONY: all xilinx clean clean-all +all: xilinx +xilinx: if_xcvr_cm.xml if_xcvr_cm_rtl.xml if_xcvr_ch.xml if_xcvr_ch_rtl.xml if_gt_qpll.xml if_gt_qpll_rtl.xml if_gt_pll.xml if_gt_pll_rtl.xml if_gt_rx.xml if_gt_rx_rtl.xml if_gt_tx.xml if_gt_tx_rtl.xml if_gt_rx_ksig.xml if_gt_rx_ksig_rtl.xml + +clean:clean-all + +clean-all: + $(call clean, \ + $(M_FLIST), \ + interface definitions) + +%.xml: $(M_DEPS) + $(call build, \ + $(M_VIVADO) interfaces_ip.tcl, \ + interfaces_ip.log, \ + interface definitions) + +#################################################################################### +#################################################################################### diff --git a/src/adi/hdl/library/interfaces/interfaces_ip.tcl b/src/adi/hdl/library/interfaces/interfaces_ip.tcl new file mode 100644 index 00000000..83bed7f7 --- /dev/null +++ b/src/adi/hdl/library/interfaces/interfaces_ip.tcl @@ -0,0 +1,99 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_if_define if_xcvr_cm +adi_if_ports output 1 enb +adi_if_ports output 12 addr +adi_if_ports output 1 wr +adi_if_ports output 16 wdata +adi_if_ports input 16 rdata +adi_if_ports input 1 ready + +adi_if_define if_xcvr_ch +adi_if_ports input 1 pll_locked +adi_if_ports output 1 rst +adi_if_ports output 1 user_ready +adi_if_ports input 1 rst_done +adi_if_ports output 1 lpm_dfe_n +adi_if_ports output 3 rate +adi_if_ports output 2 sys_clk_sel +adi_if_ports output 3 out_clk_sel +adi_if_ports output 4 tx_diffctrl +adi_if_ports output 5 tx_postcursor +adi_if_ports output 5 tx_precursor +adi_if_ports output 1 enb +adi_if_ports output 12 addr +adi_if_ports output 1 wr +adi_if_ports output 16 wdata +adi_if_ports input 16 rdata +adi_if_ports input 1 ready + +adi_if_define if_gt_qpll +adi_if_ports output 1 qpll_rst reset +adi_if_ports output 1 qpll_ref_clk clock + +adi_if_define if_gt_pll +adi_if_ports output 1 cpll_rst_m reset +adi_if_ports output 1 cpll_ref_clk_in clock + +adi_if_define if_gt_rx +adi_if_ports output 1 rx_p +adi_if_ports output 1 rx_n +adi_if_ports input 1 rx_rst reset +adi_if_ports output 1 rx_rst_m reset +adi_if_ports input 1 rx_pll_rst reset +adi_if_ports input 1 rx_gt_rst reset +adi_if_ports output 1 rx_gt_rst_m reset +adi_if_ports input 1 rx_pll_locked +adi_if_ports output 1 rx_pll_locked_m +adi_if_ports input 1 rx_user_ready +adi_if_ports output 1 rx_user_ready_m +adi_if_ports input 1 rx_rst_done +adi_if_ports output 1 rx_rst_done_m +adi_if_ports input 1 rx_out_clk clock +adi_if_ports output 1 rx_clk clock +adi_if_ports output 1 rx_sysref +adi_if_ports input 1 rx_sync +adi_if_ports input 1 rx_sof +adi_if_ports input 32 rx_data +adi_if_ports input 1 rx_ip_rst reset +adi_if_ports output 4 rx_ip_sof +adi_if_ports output 32 rx_ip_data +adi_if_ports input 1 rx_ip_sysref +adi_if_ports output 1 rx_ip_sync +adi_if_ports input 1 rx_ip_rst_done + +adi_if_define if_gt_tx +adi_if_ports input 1 tx_p +adi_if_ports input 1 tx_n +adi_if_ports input 1 tx_rst reset +adi_if_ports output 1 tx_rst_m reset +adi_if_ports input 1 tx_pll_rst reset +adi_if_ports input 1 tx_gt_rst reset +adi_if_ports output 1 tx_gt_rst_m reset +adi_if_ports input 1 tx_pll_locked +adi_if_ports output 1 tx_pll_locked_m +adi_if_ports input 1 tx_user_ready +adi_if_ports output 1 tx_user_ready_m +adi_if_ports input 1 tx_rst_done +adi_if_ports output 1 tx_rst_done_m +adi_if_ports input 1 tx_out_clk clock +adi_if_ports output 1 tx_clk clock +adi_if_ports output 1 tx_sysref +adi_if_ports output 1 tx_sync +adi_if_ports output 32 tx_data +adi_if_ports input 1 tx_ip_rst reset +adi_if_ports input 32 tx_ip_data +adi_if_ports input 1 tx_ip_sysref +adi_if_ports input 1 tx_ip_sync +adi_if_ports input 1 tx_ip_rst_done + +adi_if_define if_gt_rx_ksig +adi_if_ports output 4 rx_gt_ilas_f +adi_if_ports output 4 rx_gt_ilas_q +adi_if_ports output 4 rx_gt_ilas_a +adi_if_ports output 4 rx_gt_ilas_r +adi_if_ports output 4 rx_gt_cgs_k + diff --git a/src/adi/hdl/library/util_axis_fifo/Makefile b/src/adi/hdl/library/util_axis_fifo/Makefile new file mode 100644 index 00000000..d76109dd --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/Makefile @@ -0,0 +1,18 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := util_axis_fifo + +GENERIC_DEPS += ../common/ad_mem.v +GENERIC_DEPS += address_gray.v +GENERIC_DEPS += address_gray_pipelined.v +GENERIC_DEPS += address_sync.v +GENERIC_DEPS += util_axis_fifo.v + +XILINX_DEPS += util_axis_fifo_ip.tcl + +XILINX_LIB_DEPS += util_cdc + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/util_axis_fifo/address_gray.v b/src/adi/hdl/library/util_axis_fifo/address_gray.v new file mode 100644 index 00000000..a3eb5e25 --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/address_gray.v @@ -0,0 +1,155 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module fifo_address_gray #( + parameter ADDRESS_WIDTH = 4 +) ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output reg m_axis_valid, + output reg [ADDRESS_WIDTH:0] m_axis_level, + + input s_axis_aclk, + input s_axis_aresetn, + output reg s_axis_ready, + input s_axis_valid, + output reg s_axis_empty, + output [ADDRESS_WIDTH-1:0] s_axis_waddr, + output reg [ADDRESS_WIDTH:0] s_axis_room +); + +reg [ADDRESS_WIDTH:0] _s_axis_waddr = 'h00; +reg [ADDRESS_WIDTH:0] _s_axis_waddr_next; + +reg [ADDRESS_WIDTH:0] _m_axis_raddr = 'h00; +reg [ADDRESS_WIDTH:0] _m_axis_raddr_next; + +reg [ADDRESS_WIDTH:0] s_axis_waddr_gray = 'h00; +wire [ADDRESS_WIDTH:0] s_axis_waddr_gray_next; +wire [ADDRESS_WIDTH:0] s_axis_raddr_gray; + +reg [ADDRESS_WIDTH:0] m_axis_raddr_gray = 'h00; +wire [ADDRESS_WIDTH:0] m_axis_raddr_gray_next; +wire [ADDRESS_WIDTH:0] m_axis_waddr_gray; + +assign s_axis_waddr = _s_axis_waddr[ADDRESS_WIDTH-1:0]; + +always @(*) +begin + if (s_axis_ready && s_axis_valid) + _s_axis_waddr_next <= _s_axis_waddr + 1; + else + _s_axis_waddr_next <= _s_axis_waddr; +end + +assign s_axis_waddr_gray_next = _s_axis_waddr_next ^ _s_axis_waddr_next[ADDRESS_WIDTH:1]; + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + _s_axis_waddr <= 'h00; + s_axis_waddr_gray <= 'h00; + end else begin + _s_axis_waddr <= _s_axis_waddr_next; + s_axis_waddr_gray <= s_axis_waddr_gray_next; + end +end + +always @(*) +begin + if (m_axis_ready && m_axis_valid) + _m_axis_raddr_next <= _m_axis_raddr + 1; + else + _m_axis_raddr_next <= _m_axis_raddr; +end + +assign m_axis_raddr_gray_next = _m_axis_raddr_next ^ _m_axis_raddr_next[ADDRESS_WIDTH:1]; + +always @(posedge m_axis_aclk) +begin + if (m_axis_aresetn == 1'b0) begin + _m_axis_raddr <= 'h00; + m_axis_raddr_gray <= 'h00; + end else begin + _m_axis_raddr <= _m_axis_raddr_next; + m_axis_raddr_gray <= m_axis_raddr_gray_next; + end +end + +sync_bits #( + .NUM_OF_BITS(ADDRESS_WIDTH + 1) +) i_waddr_sync ( + .out_clk(m_axis_aclk), + .out_resetn(m_axis_aresetn), + .in(s_axis_waddr_gray), + .out(m_axis_waddr_gray) +); + +sync_bits #( + .NUM_OF_BITS(ADDRESS_WIDTH + 1) +) i_raddr_sync ( + .out_clk(s_axis_aclk), + .out_resetn(s_axis_aresetn), + .in(m_axis_raddr_gray), + .out(s_axis_raddr_gray) +); + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + s_axis_ready <= 1'b1; + s_axis_empty <= 1'b1; + end else begin + s_axis_ready <= (s_axis_raddr_gray[ADDRESS_WIDTH] == s_axis_waddr_gray_next[ADDRESS_WIDTH] || + s_axis_raddr_gray[ADDRESS_WIDTH-1] == s_axis_waddr_gray_next[ADDRESS_WIDTH-1] || + s_axis_raddr_gray[ADDRESS_WIDTH-2:0] != s_axis_waddr_gray_next[ADDRESS_WIDTH-2:0]); + s_axis_empty <= s_axis_raddr_gray == s_axis_waddr_gray_next; + end +end + +always @(posedge m_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) + m_axis_valid <= 1'b0; + else begin + m_axis_valid <= m_axis_waddr_gray != m_axis_raddr_gray_next; + end +end + +endmodule + diff --git a/src/adi/hdl/library/util_axis_fifo/address_gray_pipelined.v b/src/adi/hdl/library/util_axis_fifo/address_gray_pipelined.v new file mode 100644 index 00000000..1b255543 --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/address_gray_pipelined.v @@ -0,0 +1,152 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module fifo_address_gray_pipelined #( + parameter ADDRESS_WIDTH = 4 +) ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output reg m_axis_valid, + output [ADDRESS_WIDTH-1:0] m_axis_raddr, + output reg [ADDRESS_WIDTH:0] m_axis_level, + + input s_axis_aclk, + input s_axis_aresetn, + output reg s_axis_ready, + input s_axis_valid, + output reg s_axis_empty, + output [ADDRESS_WIDTH-1:0] s_axis_waddr, + output reg [ADDRESS_WIDTH:0] s_axis_room +); + +localparam MAX_ROOM = {1'b1,{ADDRESS_WIDTH{1'b0}}}; + +reg [ADDRESS_WIDTH:0] _s_axis_waddr = 'h00; +reg [ADDRESS_WIDTH:0] _s_axis_waddr_next; +wire [ADDRESS_WIDTH:0] _s_axis_raddr; + +reg [ADDRESS_WIDTH:0] _m_axis_raddr = 'h00; +reg [ADDRESS_WIDTH:0] _m_axis_raddr_next; +wire [ADDRESS_WIDTH:0] _m_axis_waddr; + +assign s_axis_waddr = _s_axis_waddr[ADDRESS_WIDTH-1:0]; +assign m_axis_raddr = _m_axis_raddr[ADDRESS_WIDTH-1:0]; + +always @(*) +begin + if (s_axis_ready && s_axis_valid) + _s_axis_waddr_next <= _s_axis_waddr + 1'b1; + else + _s_axis_waddr_next <= _s_axis_waddr; +end + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + _s_axis_waddr <= 'h00; + end else begin + _s_axis_waddr <= _s_axis_waddr_next; + end +end + +always @(*) +begin + if (m_axis_ready && m_axis_valid) + _m_axis_raddr_next <= _m_axis_raddr + 1'b1; + else + _m_axis_raddr_next <= _m_axis_raddr; +end + +always @(posedge m_axis_aclk) +begin + if (m_axis_aresetn == 1'b0) begin + _m_axis_raddr <= 'h00; + end else begin + _m_axis_raddr <= _m_axis_raddr_next; + end +end + +sync_gray #( + .DATA_WIDTH(ADDRESS_WIDTH + 1) +) i_waddr_sync ( + .in_clk(s_axis_aclk), + .in_resetn(s_axis_aresetn), + .out_clk(m_axis_aclk), + .out_resetn(m_axis_aresetn), + .in_count(_s_axis_waddr), + .out_count(_m_axis_waddr) +); + +sync_gray #( + .DATA_WIDTH(ADDRESS_WIDTH + 1) +) i_raddr_sync ( + .in_clk(m_axis_aclk), + .in_resetn(m_axis_aresetn), + .out_clk(s_axis_aclk), + .out_resetn(s_axis_aresetn), + .in_count(_m_axis_raddr), + .out_count(_s_axis_raddr) +); + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + s_axis_ready <= 1'b1; + s_axis_empty <= 1'b1; + s_axis_room <= MAX_ROOM; + end else begin + s_axis_ready <= (_s_axis_raddr[ADDRESS_WIDTH] == _s_axis_waddr_next[ADDRESS_WIDTH] || + _s_axis_raddr[ADDRESS_WIDTH-1:0] != _s_axis_waddr_next[ADDRESS_WIDTH-1:0]); + s_axis_empty <= _s_axis_raddr == _s_axis_waddr_next; + s_axis_room <= _s_axis_raddr - _s_axis_waddr_next + MAX_ROOM; + end +end + +always @(posedge m_axis_aclk) +begin + if (m_axis_aresetn == 1'b0) begin + m_axis_valid <= 1'b0; + m_axis_level <= 'h00; + end else begin + m_axis_valid <= _m_axis_waddr != _m_axis_raddr_next; + m_axis_level <= _m_axis_waddr - _m_axis_raddr_next; + end +end + +endmodule + diff --git a/src/adi/hdl/library/util_axis_fifo/address_sync.v b/src/adi/hdl/library/util_axis_fifo/address_sync.v new file mode 100644 index 00000000..c6b074f2 --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/address_sync.v @@ -0,0 +1,109 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module fifo_address_sync #( + parameter ADDRESS_WIDTH = 4 +) ( + input clk, + input resetn, + + input m_axis_ready, + output reg m_axis_valid, + output reg [ADDRESS_WIDTH-1:0] m_axis_raddr, + output [ADDRESS_WIDTH:0] m_axis_level, + + output reg s_axis_ready, + input s_axis_valid, + output reg s_axis_empty, + output reg [ADDRESS_WIDTH-1:0] s_axis_waddr, + output [ADDRESS_WIDTH:0] s_axis_room +); + +localparam MAX_ROOM = {1'b1,{ADDRESS_WIDTH{1'b0}}}; + +reg [ADDRESS_WIDTH:0] room = MAX_ROOM; +reg [ADDRESS_WIDTH:0] level = 'h00; +reg [ADDRESS_WIDTH:0] level_next; + +assign s_axis_room = room; +assign m_axis_level = level; + +wire read = m_axis_ready & m_axis_valid; +wire write = s_axis_ready & s_axis_valid; + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + s_axis_waddr <= 'h00; + m_axis_raddr <= 'h00; + end else begin + if (write) + s_axis_waddr <= s_axis_waddr + 1'b1; + if (read) + m_axis_raddr <= m_axis_raddr + 1'b1; + end +end + +always @(*) +begin + if (read & ~write) + level_next <= level - 1'b1; + else if (~read & write) + level_next <= level + 1'b1; + else + level_next <= level; +end + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + m_axis_valid <= 1'b0; + s_axis_ready <= 1'b0; + level <= 'h00; + room <= MAX_ROOM; + s_axis_empty <= 'h00; + end else begin + level <= level_next; + room <= MAX_ROOM - level_next; + m_axis_valid <= level_next != 0; + s_axis_ready <= level_next != MAX_ROOM; + s_axis_empty <= level_next == 0; + end +end + +endmodule + diff --git a/src/adi/hdl/library/util_axis_fifo/util_axis_fifo.v b/src/adi/hdl/library/util_axis_fifo/util_axis_fifo.v new file mode 100644 index 00000000..20316207 --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/util_axis_fifo.v @@ -0,0 +1,243 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module util_axis_fifo #( + parameter DATA_WIDTH = 64, + parameter ASYNC_CLK = 1, + parameter ADDRESS_WIDTH = 4, + parameter S_AXIS_REGISTERED = 1 +) ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output m_axis_valid, + output [DATA_WIDTH-1:0] m_axis_data, + output [ADDRESS_WIDTH:0] m_axis_level, + + input s_axis_aclk, + input s_axis_aresetn, + output s_axis_ready, + input s_axis_valid, + input [DATA_WIDTH-1:0] s_axis_data, + output s_axis_empty, + output [ADDRESS_WIDTH:0] s_axis_room +); + +generate if (ADDRESS_WIDTH == 0) begin + + reg [DATA_WIDTH-1:0] cdc_sync_fifo_ram; + reg s_axis_waddr = 1'b0; + reg m_axis_raddr = 1'b0; + + wire m_axis_waddr; + wire s_axis_raddr; + + sync_bits #( + .NUM_OF_BITS(1), + .ASYNC_CLK(ASYNC_CLK) + ) i_waddr_sync ( + .out_clk(m_axis_aclk), + .out_resetn(m_axis_aresetn), + .in(s_axis_waddr), + .out(m_axis_waddr) + ); + + sync_bits #( + .NUM_OF_BITS(1), + .ASYNC_CLK(ASYNC_CLK) + ) i_raddr_sync ( + .out_clk(s_axis_aclk), + .out_resetn(s_axis_aresetn), + .in(m_axis_raddr), + .out(s_axis_raddr) + ); + + assign m_axis_valid = m_axis_raddr != m_axis_waddr; + assign m_axis_level = m_axis_valid; + assign s_axis_ready = s_axis_raddr == s_axis_waddr; + assign s_axis_empty = s_axis_ready; + assign s_axis_room = s_axis_ready; + + always @(posedge s_axis_aclk) begin + if (s_axis_ready == 1'b1 && s_axis_valid == 1'b1) + cdc_sync_fifo_ram <= s_axis_data; + end + + always @(posedge s_axis_aclk) begin + if (s_axis_aresetn == 1'b0) begin + s_axis_waddr <= 1'b0; + end else begin + if (s_axis_ready & s_axis_valid) begin + s_axis_waddr <= s_axis_waddr + 1'b1; + end + end + end + + always @(posedge m_axis_aclk) begin + if (m_axis_aresetn == 1'b0) begin + m_axis_raddr <= 1'b0; + end else begin + if (m_axis_valid & m_axis_ready) + m_axis_raddr <= m_axis_raddr + 1'b1; + end + end + + assign m_axis_data = cdc_sync_fifo_ram; + +end else begin + + reg [DATA_WIDTH-1:0] ram[0:2**ADDRESS_WIDTH-1]; + + wire [ADDRESS_WIDTH-1:0] s_axis_waddr; + wire [ADDRESS_WIDTH-1:0] m_axis_raddr; + wire _m_axis_ready; + wire _m_axis_valid; + + wire s_mem_write; + wire m_mem_read; + + reg valid; + + always @(posedge m_axis_aclk) begin + if (m_axis_aresetn == 1'b0) begin + valid <= 1'b0; + end else begin + if (_m_axis_valid) + valid <= 1'b1; + else if (m_axis_ready) + valid <= 1'b0; + end + end + + assign s_mem_write = s_axis_ready & s_axis_valid; + assign m_mem_read = (~valid || m_axis_ready) && _m_axis_valid; + + if (ASYNC_CLK == 1) begin + + // The assumption is that in this mode the S_AXIS_REGISTERED is 1 + + fifo_address_gray_pipelined #( + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) i_address_gray ( + .m_axis_aclk(m_axis_aclk), + .m_axis_aresetn(m_axis_aresetn), + .m_axis_ready(_m_axis_ready), + .m_axis_valid(_m_axis_valid), + .m_axis_raddr(m_axis_raddr), + .m_axis_level(m_axis_level), + + .s_axis_aclk(s_axis_aclk), + .s_axis_aresetn(s_axis_aresetn), + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_empty(s_axis_empty), + .s_axis_waddr(s_axis_waddr), + .s_axis_room(s_axis_room) + ); + + // When the clocks are asynchronous instantiate a block RAM + // regardless of the requested size to make sure we threat the + // clock crossing correctly + ad_mem #( + .DATA_WIDTH (DATA_WIDTH), + .ADDRESS_WIDTH (ADDRESS_WIDTH)) + i_mem ( + .clka(s_axis_aclk), + .wea(s_mem_write), + .addra(s_axis_waddr), + .dina(s_axis_data), + .clkb(m_axis_aclk), + .reb(m_mem_read), + .addrb(m_axis_raddr), + .doutb(m_axis_data) + ); + + assign _m_axis_ready = ~valid || m_axis_ready; + assign m_axis_valid = valid; + + end else begin + + fifo_address_sync #( + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) i_address_sync ( + .clk(m_axis_aclk), + .resetn(m_axis_aresetn), + .m_axis_ready(_m_axis_ready), + .m_axis_valid(_m_axis_valid), + .m_axis_raddr(m_axis_raddr), + .m_axis_level(m_axis_level), + + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_empty(s_axis_empty), + .s_axis_waddr(s_axis_waddr), + .s_axis_room(s_axis_room) + ); + + // When the clocks are synchronous use behavioral modeling for the SDP RAM + // Let the synthesizer decide what to infer (distributed or block RAM) + always @(posedge s_axis_aclk) begin + if (s_mem_write) + ram[s_axis_waddr] <= s_axis_data; + end + + if (S_AXIS_REGISTERED == 1) begin + + reg [DATA_WIDTH-1:0] data; + + always @(posedge m_axis_aclk) begin + if (m_mem_read) + data <= ram[m_axis_raddr]; + end + + assign _m_axis_ready = ~valid || m_axis_ready; + assign m_axis_data = data; + assign m_axis_valid = valid; + + end else begin + + assign _m_axis_ready = m_axis_ready; + assign m_axis_valid = _m_axis_valid; + assign m_axis_data = ram[m_axis_raddr]; + + end + + end + +end endgenerate + +endmodule diff --git a/src/adi/hdl/library/util_axis_fifo/util_axis_fifo_ip.tcl b/src/adi/hdl/library/util_axis_fifo/util_axis_fifo_ip.tcl new file mode 100644 index 00000000..d0fc1ce4 --- /dev/null +++ b/src/adi/hdl/library/util_axis_fifo/util_axis_fifo_ip.tcl @@ -0,0 +1,41 @@ + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create util_axis_fifo +adi_ip_files util_axis_fifo [list \ + "address_gray.v" \ + "address_gray_pipelined.v" \ + "address_sync.v" \ + "../common/ad_mem.v" \ + "util_axis_fifo.v" \ +] + +adi_ip_properties_lite util_axis_fifo + +adi_ip_add_core_dependencies { \ + analog.com:user:util_cdc:1.0 \ +} + +adi_add_bus "s_axis" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + { + {"s_axis_valid" "TVALID"} \ + {"s_axis_ready" "TREADY"} \ + {"s_axis_data" "TDATA"} \ + } + +adi_add_bus "m_axis" "master" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + { + {"m_axis_valid" "TVALID"} \ + {"m_axis_ready" "TREADY"} \ + {"m_axis_data" "TDATA"} \ + } + +adi_add_bus_clock "m_axis_aclk" "m_axis" "m_axis_aresetn" +adi_add_bus_clock "s_axis_aclk" "s_axis" "m_axis_aresetn" + +ipx::save_core [ipx::current_core] diff --git a/src/adi/hdl/library/util_cdc/Makefile b/src/adi/hdl/library/util_cdc/Makefile new file mode 100644 index 00000000..26b09a09 --- /dev/null +++ b/src/adi/hdl/library/util_cdc/Makefile @@ -0,0 +1,15 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := util_cdc + +GENERIC_DEPS += sync_bits.v +GENERIC_DEPS += sync_data.v +GENERIC_DEPS += sync_event.v +GENERIC_DEPS += sync_gray.v + +XILINX_DEPS += util_cdc_ip.tcl + +include ../scripts/library.mk diff --git a/src/adi/hdl/library/util_cdc/sync_bits.v b/src/adi/hdl/library/util_cdc/sync_bits.v new file mode 100644 index 00000000..0fbcd053 --- /dev/null +++ b/src/adi/hdl/library/util_cdc/sync_bits.v @@ -0,0 +1,79 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +/* + * Helper module for synchronizing bit signals from one clock domain to another. + * It uses the standard approach of 2 FF in series. + * Note, that while the module allows to synchronize multiple bits at once it is + * only able to synchronize multi-bit signals where at max one bit changes per + * clock cycle (e.g. a gray counter). + */ + +`timescale 1ns/100ps + +module sync_bits #( + + // Number of bits to synchronize + parameter NUM_OF_BITS = 1, + // Whether input and output clocks are asynchronous, if 0 the synchronizer will + // be bypassed and the output signal equals the input signal. + parameter ASYNC_CLK = 1)( + + input [NUM_OF_BITS-1:0] in, + input out_resetn, + input out_clk, + output [NUM_OF_BITS-1:0] out); + +generate if (ASYNC_CLK == 1) begin + reg [NUM_OF_BITS-1:0] cdc_sync_stage1 = 'h0; + reg [NUM_OF_BITS-1:0] cdc_sync_stage2 = 'h0; + + always @(posedge out_clk) + begin + if (out_resetn == 1'b0) begin + cdc_sync_stage1 <= 'b0; + cdc_sync_stage2 <= 'b0; + end else begin + cdc_sync_stage1 <= in; + cdc_sync_stage2 <= cdc_sync_stage1; + end + end + + assign out = cdc_sync_stage2; +end else begin + assign out = in; +end endgenerate + +endmodule diff --git a/src/adi/hdl/library/util_cdc/sync_data.v b/src/adi/hdl/library/util_cdc/sync_data.v new file mode 100644 index 00000000..ea5fd7e5 --- /dev/null +++ b/src/adi/hdl/library/util_cdc/sync_data.v @@ -0,0 +1,97 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module sync_data #( + parameter NUM_OF_BITS = 1, + parameter ASYNC_CLK = 1 +) ( + input in_clk, + input [NUM_OF_BITS-1:0] in_data, + input out_clk, + output reg [NUM_OF_BITS-1:0] out_data +); + +generate +if (ASYNC_CLK == 1) begin + +wire out_toggle; +wire in_toggle; + +reg out_toggle_d1 = 1'b0; +reg in_toggle_d1 = 1'b0; + +reg [NUM_OF_BITS-1:0] cdc_hold; + +sync_bits i_sync_out ( + .in(in_toggle_d1), + .out_clk(out_clk), + .out_resetn(1'b1), + .out(out_toggle) +); + +sync_bits i_sync_in ( + .in(out_toggle_d1), + .out_clk(in_clk), + .out_resetn(1'b1), + .out(in_toggle) +); + +wire in_load = in_toggle == in_toggle_d1; +wire out_load = out_toggle ^ out_toggle_d1; + +always @(posedge in_clk) begin + if (in_load == 1'b1) begin + cdc_hold <= in_data; + in_toggle_d1 <= ~in_toggle_d1; + end +end + +always @(posedge out_clk) begin + if (out_load == 1'b1) begin + out_data <= cdc_hold; + end + out_toggle_d1 <= out_toggle; +end + +end else begin + always @(*) begin + out_data <= in_data; + end +end +endgenerate + +endmodule diff --git a/src/adi/hdl/library/util_cdc/sync_event.v b/src/adi/hdl/library/util_cdc/sync_event.v new file mode 100644 index 00000000..4c72e8b4 --- /dev/null +++ b/src/adi/hdl/library/util_cdc/sync_event.v @@ -0,0 +1,120 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module sync_event #( + parameter NUM_OF_EVENTS = 1, + parameter ASYNC_CLK = 1 +) ( + input in_clk, + input [NUM_OF_EVENTS-1:0] in_event, + input out_clk, + output reg [NUM_OF_EVENTS-1:0] out_event +); + +generate +if (ASYNC_CLK == 1) begin + +wire out_toggle; +wire in_toggle; + +reg out_toggle_d1 = 1'b0; +reg in_toggle_d1 = 1'b0; + +sync_bits i_sync_out ( + .in(in_toggle_d1), + .out_clk(out_clk), + .out_resetn(1'b1), + .out(out_toggle) +); + +sync_bits i_sync_in ( + .in(out_toggle_d1), + .out_clk(in_clk), + .out_resetn(1'b1), + .out(in_toggle) +); + +wire in_ready = in_toggle == in_toggle_d1; +wire load_out = out_toggle ^ out_toggle_d1; + +reg [NUM_OF_EVENTS-1:0] in_event_sticky = 'h00; +wire [NUM_OF_EVENTS-1:0] pending_events = in_event_sticky | in_event; +wire [NUM_OF_EVENTS-1:0] out_event_s; + +always @(posedge in_clk) begin + if (in_ready == 1'b1) begin + in_event_sticky <= {NUM_OF_EVENTS{1'b0}}; + if (|pending_events == 1'b1) begin + in_toggle_d1 <= ~in_toggle_d1; + end + end else begin + in_event_sticky <= pending_events; + end +end + +if (NUM_OF_EVENTS > 1) begin + reg [NUM_OF_EVENTS-1:0] cdc_hold = 'h00; + + always @(posedge in_clk) begin + if (in_ready == 1'b1) begin + cdc_hold <= pending_events; + end + end + + assign out_event_s = cdc_hold; +end else begin + // When there is only one event, we know that it is set. + assign out_event_s = 1'b1; +end + +always @(posedge out_clk) begin + if (load_out == 1'b1) begin + out_event <= out_event_s; + end else begin + out_event <= {NUM_OF_EVENTS{1'b0}}; + end + out_toggle_d1 <= out_toggle; +end + +end else begin + always @(*) begin + out_event <= in_event; + end +end +endgenerate + +endmodule diff --git a/src/adi/hdl/library/util_cdc/sync_gray.v b/src/adi/hdl/library/util_cdc/sync_gray.v new file mode 100644 index 00000000..9382d9dd --- /dev/null +++ b/src/adi/hdl/library/util_cdc/sync_gray.v @@ -0,0 +1,115 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +/* + * Helper module for synchronizing a counter from one clock domain to another + * using gray code. To work correctly the counter must not change its value by + * more than one in one clock cycle in the source domain. I.e. the value may + * change by either -1, 0 or +1. + */ + +`timescale 1ns/100ps + +module sync_gray #( + + // Bit-width of the counter + parameter DATA_WIDTH = 1, + // Whether the input and output clock are asynchronous, if set to 0 the + // synchronizer will be bypassed and out_count will be in_count. + parameter ASYNC_CLK = 1)( + + input in_clk, + input in_resetn, + input [DATA_WIDTH-1:0] in_count, + input out_resetn, + input out_clk, + output [DATA_WIDTH-1:0] out_count); + +generate if (ASYNC_CLK == 1) begin + reg [DATA_WIDTH-1:0] cdc_sync_stage0 = 'h0; + reg [DATA_WIDTH-1:0] cdc_sync_stage1 = 'h0; + reg [DATA_WIDTH-1:0] cdc_sync_stage2 = 'h0; + reg [DATA_WIDTH-1:0] out_count_m = 'h0; + + function [DATA_WIDTH-1:0] g2b; + input [DATA_WIDTH-1:0] g; + reg [DATA_WIDTH-1:0] b; + integer i; + begin + b[DATA_WIDTH-1] = g[DATA_WIDTH-1]; + for (i = DATA_WIDTH - 2; i >= 0; i = i - 1) + b[i] = b[i + 1] ^ g[i]; + g2b = b; + end + endfunction + + function [DATA_WIDTH-1:0] b2g; + input [DATA_WIDTH-1:0] b; + reg [DATA_WIDTH-1:0] g; + integer i; + begin + g[DATA_WIDTH-1] = b[DATA_WIDTH-1]; + for (i = DATA_WIDTH - 2; i >= 0; i = i -1) + g[i] = b[i + 1] ^ b[i]; + b2g = g; + end + endfunction + + always @(posedge in_clk) begin + if (in_resetn == 1'b0) begin + cdc_sync_stage0 <= 'h00; + end else begin + cdc_sync_stage0 <= b2g(in_count); + end + end + + always @(posedge out_clk) begin + if (out_resetn == 1'b0) begin + cdc_sync_stage1 <= 'h00; + cdc_sync_stage2 <= 'h00; + out_count_m <= 'h00; + end else begin + cdc_sync_stage1 <= cdc_sync_stage0; + cdc_sync_stage2 <= cdc_sync_stage1; + out_count_m <= g2b(cdc_sync_stage2); + end + end + + assign out_count = out_count_m; +end else begin + assign out_count = in_count; +end endgenerate + +endmodule diff --git a/src/adi/hdl/library/util_cdc/util_cdc_constr.tcl b/src/adi/hdl/library/util_cdc/util_cdc_constr.tcl new file mode 100644 index 00000000..320b114c --- /dev/null +++ b/src/adi/hdl/library/util_cdc/util_cdc_constr.tcl @@ -0,0 +1,58 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +# +# Each core or library found in this collection may have its own licensing terms. +# The user should keep this in in mind while exploring these cores. +# +# Redistribution and use in source and binary forms, +# with or without modification of this file, are permitted under the terms of either +# (at the option of the user): +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory, or at: +# https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +# +# OR +# +# 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +# https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +# +# *************************************************************************** +# *************************************************************************** + +proc util_cdc_sync_bits_constr {inst {from {}}} { + if {$from != {}} { + set_false_path \ + -from [get_registers $from] \ + -to [get_registers [format "%s%s" ${inst} {|cdc_sync_stage1[0]}]] + } else { + set_false_path \ + -to [get_registers [format "%s%s" ${inst} {|cdc_sync_stage1[0]}]] + } +} + +proc util_cdc_sync_data_constr {inst} { + util_cdc_sync_bits_constr ${inst}|sync_bits:i_sync_out ${inst}|in_toggle_d1 + util_cdc_sync_bits_constr ${inst}|sync_bits:i_sync_in ${inst}|out_toggle_d1 + + # set_max_skew + set_false_path \ + -from [get_registers [format "%s%s" ${inst} {|cdc_hold[*]}]] \ + -to [get_registers [format "%s%s" ${inst} {|out_data[*]}]] +} + +proc util_cdc_sync_event_constr {inst} { + util_cdc_sync_bits_constr ${inst}|sync_bits:i_sync_out ${inst}|in_toggle_d1 + util_cdc_sync_bits_constr ${inst}|sync_bits:i_sync_in ${inst}|out_toggle_d1 + + set cdc_hold_reg [get_registers -nowarn [format "%s%s" ${inst} {|cdc_hold[*]}]] + + # For a event synchronizer with one event there is no hold register + if {[get_collection_size ${cdc_hold_reg}] != 0} { + # set_max_skew + set_false_path \ + -from ${cdc_hold_reg} \ + -to [get_registers [format "%s%s" ${inst} {|out_event[*]}]] + } +} diff --git a/src/adi/hdl/library/util_cdc/util_cdc_ip.tcl b/src/adi/hdl/library/util_cdc/util_cdc_ip.tcl new file mode 100644 index 00000000..a1bce94b --- /dev/null +++ b/src/adi/hdl/library/util_cdc/util_cdc_ip.tcl @@ -0,0 +1,43 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +# +# Each core or library found in this collection may have its own licensing terms. +# The user should keep this in in mind while exploring these cores. +# +# Redistribution and use in source and binary forms, +# with or without modification of this file, are permitted under the terms of either +# (at the option of the user): +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory, or at: +# https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +# +# OR +# +# 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +# https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +# +# *************************************************************************** +# *************************************************************************** + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create util_cdc + +add_files -fileset [get_filesets sources_1] [list \ + "sync_gray.v" \ + "sync_bits.v" \ + "sync_data.v" \ + "sync_event.v" \ +] + +adi_ip_properties_lite util_cdc + +set_property name "util_cdc" [ipx::current_core] +set_property display_name "ADI Clock-Domain-Crossing Utils" [ipx::current_core] +set_property description "ADI Clock-Domain-Crossing Utils" [ipx::current_core] +set_property hide_in_gui {1} [ipx::current_core] + +ipx::save_core [ipx::current_core] From e6b71be972df2175861d3134a3a95d55d223e733 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 16:10:25 -0400 Subject: [PATCH 22/30] adi: hdl: Add xi_dmac IP to Makefile --- src/adi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adi/Makefile b/src/adi/Makefile index 5fe235d5..16085fce 100644 --- a/src/adi/Makefile +++ b/src/adi/Makefile @@ -1,5 +1,5 @@ LIBRARY := ./hdl/library -IPS := axi_clkgen axi_hdmi_tx axi_spdif_tx +IPS := axi_clkgen axi_hdmi_tx axi_spdif_tx axi_dmac .PHONY: all clean From 419fdf24163e818461951d825e85ff9ea97d0467 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 16:58:29 -0400 Subject: [PATCH 23/30] parallella/fpga: hdmi: Mimic ADI reference design We do the same thing as this commit in analogdevicesinc/hdl.git commit a0e3997687a32933c0bef3e255430199a5e8c3c1 Author: AndreiGrozav Date: Fri May 11 18:42:59 2018 +0300 common/zed_system_bd.tcl: Replace VDMA Replace Xilinx VDMA IP with ADI axi_dmac IP. Not tested. --- .../fpga/hdmi_e16_z7010/system_bd.tcl | 41 ++++++++++--------- .../fpga/hdmi_e16_z7020/system_bd.tcl | 41 ++++++++++--------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl index 67db1bb3..818c8d92 100644 --- a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl @@ -128,9 +128,9 @@ xilinx.com:ip:proc_sys_reset:5.0\ xilinx.com:ip:processing_system7:5.5\ xilinx.com:ip:xlconcat:2.1\ analog.com:user:axi_clkgen:1.0\ +analog.com:user:axi_dmac:1.0\ analog.com:user:axi_hdmi_tx:1.0\ analog.com:user:axi_spdif_tx:1.0\ -xilinx.com:ip:axi_vdma:6.3\ xilinx.com:ip:clk_wiz:6.0\ " @@ -219,6 +219,15 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create instance: axi_clkgen_0, and set properties set axi_clkgen_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_clkgen:1.0 axi_clkgen_0 ] + # Create instance: axi_dmac_0, and set properties + set axi_dmac_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_dmac:1.0 axi_dmac_0 ] + set_property -dict [ list \ + CONFIG.CYCLIC {true} \ + CONFIG.DMA_2D_TRANSFER {true} \ + CONFIG.DMA_TYPE_DEST {1} \ + CONFIG.DMA_TYPE_SRC {0} \ + ] $axi_dmac_0 + # Create instance: axi_hdmi_tx_0, and set properties set axi_hdmi_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_hdmi_tx:1.0 axi_hdmi_tx_0 ] @@ -235,14 +244,6 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.S_AXI_ADDRESS_WIDTH {16} \ ] $axi_spdif_tx_0 - # Create instance: axi_vdma_0, and set properties - set axi_vdma_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_vdma:6.3 axi_vdma_0 ] - set_property -dict [ list \ - CONFIG.c_include_s2mm {0} \ - CONFIG.c_m_axis_mm2s_tdata_width {64} \ - CONFIG.c_use_mm2s_fsync {1} \ - ] $axi_vdma_0 - # Create instance: clk_wiz_0, and set properties set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] set_property -dict [ list \ @@ -272,30 +273,30 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create interface connections connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] - connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_vdma_0/S_AXI_LITE] + connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_dmac_0/s_axi] + connect_bd_intf_net -intf_net axi_dmac_0_m_src_axi [get_bd_intf_pins axi_dmac_0/m_src_axi] [get_bd_intf_pins axi_interconnect_0/S00_AXI] connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] - connect_bd_intf_net -intf_net axi_vdma_0_M_AXI_MM2S [get_bd_intf_pins axi_interconnect_0/S00_AXI] [get_bd_intf_pins axi_vdma_0/M_AXI_MM2S] connect_bd_intf_net -intf_net s_axi1_1 [get_bd_intf_pins s_axi1] [get_bd_intf_pins axi_clkgen_0/s_axi] connect_bd_intf_net -intf_net s_axi2_1 [get_bd_intf_pins s_axi2] [get_bd_intf_pins axi_hdmi_tx_0/s_axi] # Create port connections connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] + connect_bd_net -net axi_dmac_0_irq [get_bd_pins mm2s_introut] [get_bd_pins axi_dmac_0/irq] + connect_bd_net -net axi_dmac_0_m_axis_data [get_bd_pins axi_dmac_0/m_axis_data] [get_bd_pins axi_hdmi_tx_0/vdma_data] + connect_bd_net -net axi_dmac_0_m_axis_last [get_bd_pins axi_dmac_0/m_axis_last] [get_bd_pins axi_hdmi_tx_0/vdma_end_of_frame] + connect_bd_net -net axi_dmac_0_m_axis_valid [get_bd_pins axi_dmac_0/m_axis_valid] [get_bd_pins axi_hdmi_tx_0/vdma_valid] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] - connect_bd_net -net axi_hdmi_tx_0_vdma_fs [get_bd_pins axi_vdma_0/mm2s_fsync] - connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_hdmi_tx_0/vdma_ready] [get_bd_pins axi_vdma_0/m_axis_mm2s_tready] - connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins axi_vdma_0/axi_resetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_dmac_0/m_axis_ready] [get_bd_pins axi_hdmi_tx_0/vdma_ready] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins clk_wiz_0/resetn] connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] - connect_bd_net -net axi_vdma_0_m_axis_mm2s_tdata [get_bd_pins axi_hdmi_tx_0/vdma_data] [get_bd_pins axi_vdma_0/m_axis_mm2s_tdata] - connect_bd_net -net axi_vdma_0_m_axis_mm2s_tvalid [get_bd_pins axi_hdmi_tx_0/vdma_valid] [get_bd_pins axi_vdma_0/m_axis_mm2s_tvalid] - connect_bd_net -net axi_vdma_0_mm2s_introut [get_bd_pins mm2s_introut] [get_bd_pins axi_vdma_0/mm2s_introut] connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] - connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] [get_bd_pins axi_vdma_0/m_axi_mm2s_aclk] [get_bd_pins axi_vdma_0/m_axis_mm2s_aclk] [get_bd_pins axi_vdma_0/s_axi_lite_aclk] + connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_dmac_0/m_axis_aclk] [get_bd_pins axi_dmac_0/m_src_axi_aclk] [get_bd_pins axi_dmac_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] # Restore current instance current_bd_instance $oldCurInst @@ -894,11 +895,11 @@ proc create_root_design { parentCell } { # Create address segments create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM create_bd_addr_seg -range 0x00010000 -offset 0x66000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_clkgen_0/s_axi/axi_lite] SEG_axi_clkgen_0_axi_lite + create_bd_addr_seg -range 0x00001000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_dmac_0/s_axi/axi_lite] SEG_axi_dmac_0_axi_lite create_bd_addr_seg -range 0x00010000 -offset 0x6C000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_hdmi_tx_0/s_axi/axi_lite] SEG_axi_hdmi_tx_0_axi_lite create_bd_addr_seg -range 0x00010000 -offset 0x75C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_spdif_tx_0/s_axi/axi_lite] SEG_axi_spdif_tx_0_axi_lite - create_bd_addr_seg -range 0x00010000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_vdma_0/S_AXI_LITE/Reg] SEG_axi_vdma_0_Reg create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite - create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_vdma_0/Data_MM2S] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_dmac_0/m_src_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM # Restore current instance diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl index bc4f8ab0..d0180ad2 100644 --- a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl @@ -128,9 +128,9 @@ xilinx.com:ip:proc_sys_reset:5.0\ xilinx.com:ip:processing_system7:5.5\ xilinx.com:ip:xlconcat:2.1\ analog.com:user:axi_clkgen:1.0\ +analog.com:user:axi_dmac:1.0\ analog.com:user:axi_hdmi_tx:1.0\ analog.com:user:axi_spdif_tx:1.0\ -xilinx.com:ip:axi_vdma:6.3\ xilinx.com:ip:clk_wiz:6.0\ " @@ -219,6 +219,15 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create instance: axi_clkgen_0, and set properties set axi_clkgen_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_clkgen:1.0 axi_clkgen_0 ] + # Create instance: axi_dmac_0, and set properties + set axi_dmac_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_dmac:1.0 axi_dmac_0 ] + set_property -dict [ list \ + CONFIG.CYCLIC {true} \ + CONFIG.DMA_2D_TRANSFER {true} \ + CONFIG.DMA_TYPE_DEST {1} \ + CONFIG.DMA_TYPE_SRC {0} \ + ] $axi_dmac_0 + # Create instance: axi_hdmi_tx_0, and set properties set axi_hdmi_tx_0 [ create_bd_cell -type ip -vlnv analog.com:user:axi_hdmi_tx:1.0 axi_hdmi_tx_0 ] @@ -235,14 +244,6 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.S_AXI_ADDRESS_WIDTH {16} \ ] $axi_spdif_tx_0 - # Create instance: axi_vdma_0, and set properties - set axi_vdma_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_vdma:6.3 axi_vdma_0 ] - set_property -dict [ list \ - CONFIG.c_include_s2mm {0} \ - CONFIG.c_m_axis_mm2s_tdata_width {64} \ - CONFIG.c_use_mm2s_fsync {1} \ - ] $axi_vdma_0 - # Create instance: clk_wiz_0, and set properties set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] set_property -dict [ list \ @@ -263,30 +264,30 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create interface connections connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] - connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_vdma_0/S_AXI_LITE] + connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_dmac_0/s_axi] + connect_bd_intf_net -intf_net axi_dmac_0_m_src_axi [get_bd_intf_pins axi_dmac_0/m_src_axi] [get_bd_intf_pins axi_interconnect_0/S00_AXI] connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] - connect_bd_intf_net -intf_net axi_vdma_0_M_AXI_MM2S [get_bd_intf_pins axi_interconnect_0/S00_AXI] [get_bd_intf_pins axi_vdma_0/M_AXI_MM2S] connect_bd_intf_net -intf_net s_axi1_1 [get_bd_intf_pins s_axi1] [get_bd_intf_pins axi_clkgen_0/s_axi] connect_bd_intf_net -intf_net s_axi2_1 [get_bd_intf_pins s_axi2] [get_bd_intf_pins axi_hdmi_tx_0/s_axi] # Create port connections connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] + connect_bd_net -net axi_dmac_0_irq [get_bd_pins mm2s_introut] [get_bd_pins axi_dmac_0/irq] + connect_bd_net -net axi_dmac_0_m_axis_data [get_bd_pins axi_dmac_0/m_axis_data] [get_bd_pins axi_hdmi_tx_0/vdma_data] + connect_bd_net -net axi_dmac_0_m_axis_last [get_bd_pins axi_dmac_0/m_axis_last] [get_bd_pins axi_hdmi_tx_0/vdma_end_of_frame] + connect_bd_net -net axi_dmac_0_m_axis_valid [get_bd_pins axi_dmac_0/m_axis_valid] [get_bd_pins axi_hdmi_tx_0/vdma_valid] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] - connect_bd_net -net axi_hdmi_tx_0_vdma_fs [get_bd_pins axi_vdma_0/mm2s_fsync] - connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_hdmi_tx_0/vdma_ready] [get_bd_pins axi_vdma_0/m_axis_mm2s_tready] - connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins axi_vdma_0/axi_resetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_dmac_0/m_axis_ready] [get_bd_pins axi_hdmi_tx_0/vdma_ready] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins clk_wiz_0/resetn] connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] - connect_bd_net -net axi_vdma_0_m_axis_mm2s_tdata [get_bd_pins axi_hdmi_tx_0/vdma_data] [get_bd_pins axi_vdma_0/m_axis_mm2s_tdata] - connect_bd_net -net axi_vdma_0_m_axis_mm2s_tvalid [get_bd_pins axi_hdmi_tx_0/vdma_valid] [get_bd_pins axi_vdma_0/m_axis_mm2s_tvalid] - connect_bd_net -net axi_vdma_0_mm2s_introut [get_bd_pins mm2s_introut] [get_bd_pins axi_vdma_0/mm2s_introut] connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] - connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] [get_bd_pins axi_vdma_0/m_axi_mm2s_aclk] [get_bd_pins axi_vdma_0/m_axis_mm2s_aclk] [get_bd_pins axi_vdma_0/s_axi_lite_aclk] + connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_dmac_0/m_axis_aclk] [get_bd_pins axi_dmac_0/m_src_axi_aclk] [get_bd_pins axi_dmac_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] # Restore current instance current_bd_instance $oldCurInst @@ -885,11 +886,11 @@ proc create_root_design { parentCell } { # Create address segments create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces parallella_base_0/m_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP1/HP1_DDR_LOWOCM] SEG_processing_system7_0_HP1_DDR_LOWOCM create_bd_addr_seg -range 0x00010000 -offset 0x66000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_clkgen_0/s_axi/axi_lite] SEG_axi_clkgen_0_axi_lite + create_bd_addr_seg -range 0x00001000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_dmac_0/s_axi/axi_lite] SEG_axi_dmac_0_axi_lite create_bd_addr_seg -range 0x00010000 -offset 0x6C000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_hdmi_tx_0/s_axi/axi_lite] SEG_axi_hdmi_tx_0_axi_lite create_bd_addr_seg -range 0x00010000 -offset 0x75C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_spdif_tx_0/s_axi/axi_lite] SEG_axi_spdif_tx_0_axi_lite - create_bd_addr_seg -range 0x00010000 -offset 0x43000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs hdmi_0/axi_vdma_0/S_AXI_LITE/Reg] SEG_axi_vdma_0_Reg create_bd_addr_seg -range 0x40000000 -offset 0x80000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_base_0/s_axi/axi_lite] SEG_parallella_base_0_axi_lite - create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_vdma_0/Data_MM2S] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM + create_bd_addr_seg -range 0x40000000 -offset 0x00000000 [get_bd_addr_spaces hdmi_0/axi_dmac_0/m_src_axi] [get_bd_addr_segs processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM] SEG_processing_system7_0_HP0_DDR_LOWOCM # Restore current instance From 20b54a2198ea8dbe376e5f6650dc210d31a5c127 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Sun, 26 May 2019 20:44:30 -0400 Subject: [PATCH 24/30] parallella/fpga: hdmi z7010: Try fixing clock implementation error Apparently axi_dmac uses more resources than axi_vdma did. Relax clk_wiz_0 (used by SPDIF) as much as possible. No buffers on input or output. Unfortunately implementation still errors out because of block-RAM over-utilization: Phase 1.2 IO Placement/ Clock Placement/ Build Placer Device ERROR: [Place 30-640] Place Check : This design requires more RAMB18 and RAMB36/FIFO cells than are available in the target device. This design requires 121 of such cell types but only 120 compatible sites are available in the target device. Please analyze your synthesis results and constraints to ensure the design is mapped to Xilinx primitives as expected. If so, please consider targeting a larger device. INFO: [Timing 38-35] Done setting XDC timing constraints. Phase 1.2 IO Placement/ Clock Placement/ Build Placer Device | Checksum: 43b4e0ea --- .../fpga/hdmi_e16_z7010/system_bd.tcl | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl index 818c8d92..c367e127 100644 --- a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl @@ -247,10 +247,11 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create instance: clk_wiz_0, and set properties set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] set_property -dict [ list \ + CONFIG.AXI_DRP {false} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.CLKOUT1_DRIVES {BUFG} \ - CONFIG.CLKOUT1_JITTER {307.609} \ - CONFIG.CLKOUT1_PHASE_ERROR {262.479} \ + CONFIG.CLKOUT1_DRIVES {No_buffer} \ + CONFIG.CLKOUT1_JITTER {307.400} \ + CONFIG.CLKOUT1_PHASE_ERROR {262.328} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {12.288} \ CONFIG.CLKOUT2_DRIVES {BUFG} \ CONFIG.CLKOUT3_DRIVES {BUFG} \ @@ -258,16 +259,24 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.CLKOUT5_DRIVES {BUFG} \ CONFIG.CLKOUT6_DRIVES {BUFG} \ CONFIG.CLKOUT7_DRIVES {BUFG} \ + CONFIG.FEEDBACK_SOURCE {FDBK_ONCHIP} \ CONFIG.MMCM_CLKFBOUT_MULT_F {47} \ CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ CONFIG.MMCM_CLKOUT0_DIVIDE_F {85} \ CONFIG.MMCM_COMPENSATION {ZHOLD} \ CONFIG.MMCM_DIVCLK_DIVIDE {9} \ + CONFIG.PHASE_DUTY_CONFIG {false} \ CONFIG.PRIMITIVE {PLL} \ - CONFIG.PRIM_IN_FREQ {200} \ + CONFIG.PRIM_IN_FREQ {200.000} \ + CONFIG.PRIM_SOURCE {No_buffer} \ CONFIG.RESET_PORT {resetn} \ CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.SECONDARY_SOURCE {Single_ended_clock_capable_pin} \ + CONFIG.USE_DYN_RECONFIG {false} \ CONFIG.USE_LOCKED {false} \ + CONFIG.USE_PHASE_ALIGNMENT {false} \ + CONFIG.USE_RESET {true} \ + CONFIG.USE_SAFE_CLOCK_STARTUP {false} \ ] $clk_wiz_0 # Create interface connections @@ -494,7 +503,7 @@ proc create_root_design { parentCell } { CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {152} \ CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {200} \ - CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {20} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} \ CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ CONFIG.PCW_FPGA_FCLK2_ENABLE {1} \ From 6a61271765f5274838c070ab84c0fbb68daddeb2 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 27 May 2019 18:45:25 -0400 Subject: [PATCH 25/30] oh_memory_ram: Use LUTs over BRAM on ZYNQ There is not enough BRAM cells for the z7010 HDMI project. --- src/common/hdl/oh_memory_ram.v | 64 +++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/common/hdl/oh_memory_ram.v b/src/common/hdl/oh_memory_ram.v index 10a387f2..3465f8da 100644 --- a/src/common/hdl/oh_memory_ram.v +++ b/src/common/hdl/oh_memory_ram.v @@ -5,10 +5,15 @@ //# License: MIT (see LICENSE file in OH! repository) # //############################################################################# +`ifndef CFG_PLATFORM +`define CFG_PLATFORM "GENERIC" +`endif + module oh_memory_ram # (parameter DW = 104, //memory width parameter DEPTH = 32, //memory depth - parameter AW = $clog2(DEPTH) // address width - ) + parameter AW = $clog2(DEPTH), // address width + parameter PLATFORM = `CFG_PLATFORM + ) (// read-port input rd_clk,// rd clock input rd_en, // memory access @@ -20,28 +25,45 @@ module oh_memory_ram # (parameter DW = 104, //memory width input [AW-1:0] wr_addr, // address input [DW-1:0] wr_wem, // write enable vector input [DW-1:0] wr_din // data input - ); - - reg [DW-1:0] ram [DEPTH-1:0]; - integer i; - - //registered read port - always @ (posedge rd_clk) - if(rd_en) - rd_dout[DW-1:0] <= ram[rd_addr[AW-1:0]]; - - //write port with vector enable - always @(posedge wr_clk) - for (i=0;i Date: Mon, 27 May 2019 18:53:57 -0400 Subject: [PATCH 26/30] parallella/fgpa: HDMI: Use same SPDIF clock config for z7010 and z7020 --- .../fpga/hdmi_e16_z7020/system_bd.tcl | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl index d0180ad2..fa69c2a3 100644 --- a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl @@ -247,18 +247,36 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create instance: clk_wiz_0, and set properties set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] set_property -dict [ list \ + CONFIG.AXI_DRP {false} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.CLKOUT1_JITTER {327.996} \ - CONFIG.CLKOUT1_PHASE_ERROR {264.435} \ + CONFIG.CLKOUT1_DRIVES {No_buffer} \ + CONFIG.CLKOUT1_JITTER {307.400} \ + CONFIG.CLKOUT1_PHASE_ERROR {262.328} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {12.288} \ - CONFIG.MMCM_CLKFBOUT_MULT_F {44.375} \ + CONFIG.CLKOUT2_DRIVES {BUFG} \ + CONFIG.CLKOUT3_DRIVES {BUFG} \ + CONFIG.CLKOUT4_DRIVES {BUFG} \ + CONFIG.CLKOUT5_DRIVES {BUFG} \ + CONFIG.CLKOUT6_DRIVES {BUFG} \ + CONFIG.CLKOUT7_DRIVES {BUFG} \ + CONFIG.FEEDBACK_SOURCE {FDBK_ONCHIP} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {47} \ CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ - CONFIG.MMCM_CLKOUT0_DIVIDE_F {80.250} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {85} \ + CONFIG.MMCM_COMPENSATION {ZHOLD} \ CONFIG.MMCM_DIVCLK_DIVIDE {9} \ + CONFIG.PHASE_DUTY_CONFIG {false} \ + CONFIG.PRIMITIVE {PLL} \ CONFIG.PRIM_IN_FREQ {200.000} \ + CONFIG.PRIM_SOURCE {No_buffer} \ CONFIG.RESET_PORT {resetn} \ CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.SECONDARY_SOURCE {Single_ended_clock_capable_pin} \ + CONFIG.USE_DYN_RECONFIG {false} \ CONFIG.USE_LOCKED {false} \ + CONFIG.USE_PHASE_ALIGNMENT {false} \ + CONFIG.USE_RESET {true} \ + CONFIG.USE_SAFE_CLOCK_STARTUP {false} \ ] $clk_wiz_0 # Create interface connections From b57c799c122cae0ede3c240f9f124ae7df10d23c Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 27 May 2019 19:23:37 -0400 Subject: [PATCH 27/30] parallella/fpga: HDMI: Minor visual block design improvements Rename clk_wiz_0 to spdif_clk_0 for clarity. Use interface connection between axi_dmac_0/m_axis <--> axi_hdmi_tx_0/s_axis. --- .../fpga/hdmi_e16_z7010/system_bd.tcl | 17 +++++++---------- .../fpga/hdmi_e16_z7020/system_bd.tcl | 17 +++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl index c367e127..931cd57d 100644 --- a/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7010/system_bd.tcl @@ -244,8 +244,8 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.S_AXI_ADDRESS_WIDTH {16} \ ] $axi_spdif_tx_0 - # Create instance: clk_wiz_0, and set properties - set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] + # Create instance: spdif_clk_0, and set properties + set spdif_clk_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 spdif_clk_0 ] set_property -dict [ list \ CONFIG.AXI_DRP {false} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ @@ -277,12 +277,13 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.USE_PHASE_ALIGNMENT {false} \ CONFIG.USE_RESET {true} \ CONFIG.USE_SAFE_CLOCK_STARTUP {false} \ - ] $clk_wiz_0 + ] $spdif_clk_0 # Create interface connections connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_dmac_0/s_axi] + connect_bd_intf_net -intf_net axi_dmac_0_m_axis [get_bd_intf_pins axi_dmac_0/m_axis] [get_bd_intf_pins axi_hdmi_tx_0/s_axis] connect_bd_intf_net -intf_net axi_dmac_0_m_src_axi [get_bd_intf_pins axi_dmac_0/m_src_axi] [get_bd_intf_pins axi_interconnect_0/S00_AXI] connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] @@ -292,19 +293,15 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create port connections connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] connect_bd_net -net axi_dmac_0_irq [get_bd_pins mm2s_introut] [get_bd_pins axi_dmac_0/irq] - connect_bd_net -net axi_dmac_0_m_axis_data [get_bd_pins axi_dmac_0/m_axis_data] [get_bd_pins axi_hdmi_tx_0/vdma_data] - connect_bd_net -net axi_dmac_0_m_axis_last [get_bd_pins axi_dmac_0/m_axis_last] [get_bd_pins axi_hdmi_tx_0/vdma_end_of_frame] - connect_bd_net -net axi_dmac_0_m_axis_valid [get_bd_pins axi_dmac_0/m_axis_valid] [get_bd_pins axi_hdmi_tx_0/vdma_valid] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] - connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_dmac_0/m_axis_ready] [get_bd_pins axi_hdmi_tx_0/vdma_ready] - connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins spdif_clk_0/resetn] connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] - connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] - connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] + connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins spdif_clk_0/clk_in1] + connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins spdif_clk_0/clk_out1] connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_dmac_0/m_axis_aclk] [get_bd_pins axi_dmac_0/m_src_axi_aclk] [get_bd_pins axi_dmac_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] # Restore current instance diff --git a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl index fa69c2a3..2e99b4e1 100644 --- a/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl +++ b/src/parallella/fpga/hdmi_e16_z7020/system_bd.tcl @@ -244,8 +244,8 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.S_AXI_ADDRESS_WIDTH {16} \ ] $axi_spdif_tx_0 - # Create instance: clk_wiz_0, and set properties - set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] + # Create instance: spdif_clk_0, and set properties + set spdif_clk_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 spdif_clk_0 ] set_property -dict [ list \ CONFIG.AXI_DRP {false} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ @@ -277,12 +277,13 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { CONFIG.USE_PHASE_ALIGNMENT {false} \ CONFIG.USE_RESET {true} \ CONFIG.USE_SAFE_CLOCK_STARTUP {false} \ - ] $clk_wiz_0 + ] $spdif_clk_0 # Create interface connections connect_bd_intf_net -intf_net DMA_ACK_1 [get_bd_intf_pins DMA_ACK] [get_bd_intf_pins axi_spdif_tx_0/dma_ack] connect_bd_intf_net -intf_net S_AXI_1 [get_bd_intf_pins S_AXI] [get_bd_intf_pins axi_spdif_tx_0/s_axi] connect_bd_intf_net -intf_net S_AXI_LITE_1 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins axi_dmac_0/s_axi] + connect_bd_intf_net -intf_net axi_dmac_0_m_axis [get_bd_intf_pins axi_dmac_0/m_axis] [get_bd_intf_pins axi_hdmi_tx_0/s_axis] connect_bd_intf_net -intf_net axi_dmac_0_m_src_axi [get_bd_intf_pins axi_dmac_0/m_src_axi] [get_bd_intf_pins axi_interconnect_0/S00_AXI] connect_bd_intf_net -intf_net axi_interconnect_0_M00_AXI [get_bd_intf_pins M00_AXI] [get_bd_intf_pins axi_interconnect_0/M00_AXI] connect_bd_intf_net -intf_net axi_spdif_tx_0_DMA_REQ [get_bd_intf_pins DMA_REQ] [get_bd_intf_pins axi_spdif_tx_0/dma_req] @@ -292,19 +293,15 @@ proc create_hier_cell_hdmi_0 { parentCell nameHier } { # Create port connections connect_bd_net -net axi_clkgen_0_clk_0 [get_bd_pins axi_clkgen_0/clk_0] [get_bd_pins axi_hdmi_tx_0/hdmi_clk] connect_bd_net -net axi_dmac_0_irq [get_bd_pins mm2s_introut] [get_bd_pins axi_dmac_0/irq] - connect_bd_net -net axi_dmac_0_m_axis_data [get_bd_pins axi_dmac_0/m_axis_data] [get_bd_pins axi_hdmi_tx_0/vdma_data] - connect_bd_net -net axi_dmac_0_m_axis_last [get_bd_pins axi_dmac_0/m_axis_last] [get_bd_pins axi_hdmi_tx_0/vdma_end_of_frame] - connect_bd_net -net axi_dmac_0_m_axis_valid [get_bd_pins axi_dmac_0/m_axis_valid] [get_bd_pins axi_hdmi_tx_0/vdma_valid] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data [get_bd_pins hdmi_16_data] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_data_e [get_bd_pins hdmi_16_data_e] [get_bd_pins axi_hdmi_tx_0/hdmi_16_data_e] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_hsync [get_bd_pins hdmi_16_hsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_hsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_16_vsync [get_bd_pins hdmi_16_vsync] [get_bd_pins axi_hdmi_tx_0/hdmi_16_vsync] connect_bd_net -net axi_hdmi_tx_0_hdmi_out_clk [get_bd_pins hdmi_out_clk] [get_bd_pins axi_hdmi_tx_0/hdmi_out_clk] - connect_bd_net -net axi_hdmi_tx_0_vdma_ready [get_bd_pins axi_dmac_0/m_axis_ready] [get_bd_pins axi_hdmi_tx_0/vdma_ready] - connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins clk_wiz_0/resetn] + connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins axi_clkgen_0/s_axi_aresetn] [get_bd_pins axi_dmac_0/m_src_axi_aresetn] [get_bd_pins axi_dmac_0/s_axi_aresetn] [get_bd_pins axi_hdmi_tx_0/s_axi_aresetn] [get_bd_pins axi_interconnect_0/ARESETN] [get_bd_pins axi_interconnect_0/M00_ARESETN] [get_bd_pins axi_interconnect_0/S00_ARESETN] [get_bd_pins axi_spdif_tx_0/dma_req_rstn] [get_bd_pins axi_spdif_tx_0/s_axi_aresetn] [get_bd_pins spdif_clk_0/resetn] connect_bd_net -net axi_spdif_tx_0_spdif_tx_o [get_bd_pins spdif_tx_o] [get_bd_pins axi_spdif_tx_0/spdif_tx_o] - connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins clk_wiz_0/clk_in1] - connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins clk_wiz_0/clk_out1] + connect_bd_net -net clk_1 [get_bd_pins clk] [get_bd_pins axi_clkgen_0/clk] [get_bd_pins spdif_clk_0/clk_in1] + connect_bd_net -net clk_wiz_0_clk_out1 [get_bd_pins axi_spdif_tx_0/spdif_data_clk] [get_bd_pins spdif_clk_0/clk_out1] connect_bd_net -net s_axi_aclk_1 [get_bd_pins s_axi_aclk] [get_bd_pins axi_clkgen_0/s_axi_aclk] [get_bd_pins axi_dmac_0/m_axis_aclk] [get_bd_pins axi_dmac_0/m_src_axi_aclk] [get_bd_pins axi_dmac_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/s_axi_aclk] [get_bd_pins axi_hdmi_tx_0/vdma_clk] [get_bd_pins axi_interconnect_0/ACLK] [get_bd_pins axi_interconnect_0/M00_ACLK] [get_bd_pins axi_interconnect_0/S00_ACLK] [get_bd_pins axi_spdif_tx_0/dma_req_aclk] [get_bd_pins axi_spdif_tx_0/s_axi_aclk] # Restore current instance From c9640342e2370044633ec5ca16ef972c2c84f819 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 27 May 2019 19:25:26 -0400 Subject: [PATCH 28/30] parallella/fpga: Fix typo in Makefile clean target --- src/parallella/fpga/hdmi_e16_z7010/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parallella/fpga/hdmi_e16_z7010/Makefile b/src/parallella/fpga/hdmi_e16_z7010/Makefile index 8442c3b8..5c35a45f 100644 --- a/src/parallella/fpga/hdmi_e16_z7010/Makefile +++ b/src/parallella/fpga/hdmi_e16_z7010/Makefile @@ -15,7 +15,7 @@ M_FLIST += *.runs M_FLIST += *.srcs M_FLIST += *.sdk M_FLIST += .Xil -M_FLIST += parallella_e16_hdmi_gpiose_7021.bit.bin +M_FLIST += parallella_e16_hdmi_gpiose_7010.bit.bin M_FLIST += system_wrapper.bit.bin M_FLIST += reports M_FLIST += results From a50cdb78f3ed557ac7886fe43a34871c0277cfeb Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 27 May 2019 19:26:32 -0400 Subject: [PATCH 29/30] parallella/fpga: parallella_base Add more files to clean target --- src/parallella/fpga/parallella_base/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/parallella/fpga/parallella_base/Makefile b/src/parallella/fpga/parallella_base/Makefile index 3a5f15f7..5aa42dfc 100644 --- a/src/parallella/fpga/parallella_base/Makefile +++ b/src/parallella/fpga/parallella_base/Makefile @@ -13,6 +13,13 @@ M_FLIST += *.runs M_FLIST += *.srcs M_FLIST += *.sdk M_FLIST += .Xil +M_FLIST += component.xml +M_FLIST += ip_tmp +M_FLIST += parallella_base.hw +M_FLIST += parallella_base.ip_user_files +M_FLIST += parallella_base.zip +M_FLIST += sim +M_FLIST += src all: $(M_DEPS) $(M_VIVADO) run.tcl From 9e60a0c1747d90c6a867841295377efb78330526 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Mon, 27 May 2019 20:08:55 -0400 Subject: [PATCH 30/30] parallella/fpga: Fix timing warning WARNING: [Vivado 12-2489] -period contains time 3.333333 which will be rounded to 3.333 to ensure it is an integer multiple of 1 picosecond [/home/olaj/Projects/Adapteva/oh/src/parallella/fpga/paral lella_timing.xdc:1] --- src/parallella/fpga/parallella_timing.xdc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/parallella/fpga/parallella_timing.xdc b/src/parallella/fpga/parallella_timing.xdc index 7e84cb5f..a2450dcd 100644 --- a/src/parallella/fpga/parallella_timing.xdc +++ b/src/parallella/fpga/parallella_timing.xdc @@ -1,4 +1,2 @@ -create_clock -period 3.33333333 -name rxi_lclk_p -waveform {0.000 1.66666667} [get_ports rxi_lclk_p] - - +create_clock -period 3.333 -name rxi_lclk_p -waveform {0.000 1.667} [get_ports rxi_lclk_p]