├── Platforms └── Rhino │ ├── mkbof │ └── rhino_pins.ucf ├── README ├── Supporting ├── DFT_Arithmetic_Model │ └── DFT_Model.py ├── complex_signal_file_generator.py ├── dft_error_analysis.py └── frequency_spectrum_viewer.py └── Toolflow_Code ├── Actor.py ├── Arc.py ├── HDFT ├── Butterfly.py ├── DFT.py ├── Pipeline_Mux.py ├── Reorderer.py ├── bufferfly_dev_test_script.py ├── butterfly_dev_test_script.py ├── dft_dev_test_script.py ├── pipeline_mux_dev_test_script.py └── reorderer_dev_test_script.py ├── Old_HDFT_Code ├── Actor.py ├── DFT.py ├── DivideAndConquer.py ├── HDFT.py ├── HDFT_Performance_TestBench.v ├── Mux.py ├── Unscrambler.py ├── hdft_performance_testbench.py ├── module_dev_testbench.py └── system_dev_testbench.py ├── actor_dev_test_script.py ├── arc_dev_test_script.py └── system_dev_test_bench.py /Platforms/Rhino/mkbof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gordonei/MyHDL-based-FPGA-DSP-Toolflow/9f6065b5ee6158fc020802041f6dcc4dbc0b7de8/Platforms/Rhino/mkbof -------------------------------------------------------------------------------- /Platforms/Rhino/rhino_pins.ucf: -------------------------------------------------------------------------------- 1 | CONFIG VCCAUX=3.3; 2 | 3 | NET "FMC0_CLK0_M2C" IOSTANDARD = LVCMOS33; 4 | NET "FMC0_CLK1_M2C" IOSTANDARD = LVCMOS33; 5 | NET "FMC0_GA0" IOSTANDARD = LVCMOS33; 6 | NET "FMC0_GA1" IOSTANDARD = LVCMOS33; 7 | NET "FMC0_ZDOK_N[0]" IOSTANDARD = BLVDS_25; 8 | NET "FMC0_ZDOK_N[1]" IOSTANDARD = BLVDS_25; 9 | NET "FMC0_ZDOK_P[0]" IOSTANDARD = BLVDS_25; 10 | NET "FMC0_ZDOK_P[1]" IOSTANDARD = BLVDS_25; 11 | NET "FMC1_GA0" IOSTANDARD = LVCMOS33; 12 | NET "FMC1_GA1" IOSTANDARD = LVCMOS33; 13 | NET "FMC_I2C_SCL" IOSTANDARD = LVCMOS33; 14 | NET "FMC_I2C_SDA" IOSTANDARD = LVCMOS33; 15 | NET "FPGA_AWAKE" IOSTANDARD = LVCMOS33; 16 | NET "FPGA_PROC_BUS_A[1]" IOSTANDARD = LVCMOS33; 17 | NET "FPGA_PROC_BUS_A[2]" IOSTANDARD = LVCMOS33; 18 | NET "FPGA_PROC_BUS_A[3]" IOSTANDARD = LVCMOS33; 19 | NET "FPGA_PROC_BUS_A[4]" IOSTANDARD = LVCMOS33; 20 | NET "FPGA_PROC_BUS_A[5]" IOSTANDARD = LVCMOS33; 21 | NET "FPGA_PROC_BUS_A[6]" IOSTANDARD = LVCMOS33; 22 | NET "FPGA_PROC_BUS_A[7]" IOSTANDARD = LVCMOS33; 23 | NET "FPGA_PROC_BUS_A[8]" IOSTANDARD = LVCMOS33; 24 | NET "FPGA_PROC_BUS_A[9]" IOSTANDARD = LVCMOS33; 25 | NET "FPGA_PROC_BUS_A[10]" IOSTANDARD = LVCMOS33; 26 | NET "FPGA_PROC_BUS_BUSY0" IOSTANDARD = LVCMOS33; 27 | NET "FPGA_PROC_BUS_BUSY1" IOSTANDARD = LVCMOS33; 28 | NET "FPGA_PROC_BUS_CLK" IOSTANDARD = LVCMOS33; 29 | NET "FPGA_PROC_BUS_D[0]" IOSTANDARD = LVCMOS33; 30 | NET "FPGA_PROC_BUS_D[1]" IOSTANDARD = LVCMOS33; 31 | NET "FPGA_PROC_BUS_D[2]" IOSTANDARD = LVCMOS33; 32 | NET "FPGA_PROC_BUS_D[3]" IOSTANDARD = LVCMOS33; 33 | NET "FPGA_PROC_BUS_D[4]" IOSTANDARD = LVCMOS33; 34 | NET "FPGA_PROC_BUS_D[5]" IOSTANDARD = LVCMOS33; 35 | NET "FPGA_PROC_BUS_D[6]" IOSTANDARD = LVCMOS33; 36 | NET "FPGA_PROC_BUS_D[7]" IOSTANDARD = LVCMOS33; 37 | NET "FPGA_PROC_BUS_D[8]" IOSTANDARD = LVCMOS33; 38 | NET "FPGA_PROC_BUS_D[9]" IOSTANDARD = LVCMOS33; 39 | NET "FPGA_PROC_BUS_D[10]" IOSTANDARD = LVCMOS33; 40 | NET "FPGA_PROC_BUS_D[11]" IOSTANDARD = LVCMOS33; 41 | NET "FPGA_PROC_BUS_D[12]" IOSTANDARD = LVCMOS33; 42 | NET "FPGA_PROC_BUS_D[13]" IOSTANDARD = LVCMOS33; 43 | NET "FPGA_PROC_BUS_D[14]" IOSTANDARD = LVCMOS33; 44 | NET "FPGA_PROC_BUS_D[15]" IOSTANDARD = LVCMOS33; 45 | NET "FPGA_PROC_BUS_nADV_ALE" IOSTANDARD = LVCMOS33; 46 | NET "FPGA_PROC_BUS_nCS0" IOSTANDARD = LVCMOS33; 47 | NET "FPGA_PROC_BUS_nCS1" IOSTANDARD = LVCMOS33; 48 | NET "FPGA_PROC_BUS_nCS2" IOSTANDARD = LVCMOS33; 49 | NET "FPGA_PROC_BUS_nCS3" IOSTANDARD = LVCMOS33; 50 | NET "FPGA_PROC_BUS_nCS4" IOSTANDARD = LVCMOS33; 51 | NET "FPGA_PROC_BUS_nCS5" IOSTANDARD = LVCMOS33; 52 | NET "FPGA_PROC_BUS_nCS6" IOSTANDARD = LVCMOS33; 53 | NET "FPGA_PROC_BUS_nOE" IOSTANDARD = LVCMOS33; 54 | NET "FPGA_PROC_BUS_nWE" IOSTANDARD = LVCMOS33; 55 | NET "FPGA_PROC_BUS_nWP" IOSTANDARD = LVCMOS33; 56 | NET "FP_I2C_SCL" IOSTANDARD = LVCMOS33; 57 | NET "FP_I2C_SDA" IOSTANDARD = LVCMOS33; 58 | NET "IEEE1588_CLK" IOSTANDARD = LVCMOS33; 59 | NET "IEEE1588_GPIO[0]" IOSTANDARD = LVCMOS33; 60 | NET "IEEE1588_GPIO[1]" IOSTANDARD = LVCMOS33; 61 | NET "IEEE1588_GPIO[2]" IOSTANDARD = LVCMOS33; 62 | NET "IEEE1588_GPIO[3]" IOSTANDARD = LVCMOS33; 63 | NET "mcb4_dram_a[0]" IOSTANDARD = SSTL15_II; 64 | NET "mcb4_dram_a[1]" IOSTANDARD = SSTL15_II; 65 | NET "mcb4_dram_a[2]" IOSTANDARD = SSTL15_II; 66 | NET "mcb4_dram_a[3]" IOSTANDARD = SSTL15_II; 67 | NET "mcb4_dram_a[4]" IOSTANDARD = SSTL15_II; 68 | NET "mcb4_dram_a[5]" IOSTANDARD = SSTL15_II; 69 | NET "mcb4_dram_a[6]" IOSTANDARD = SSTL15_II; 70 | NET "mcb4_dram_a[7]" IOSTANDARD = SSTL15_II; 71 | NET "mcb4_dram_a[8]" IOSTANDARD = SSTL15_II; 72 | NET "mcb4_dram_a[9]" IOSTANDARD = SSTL15_II; 73 | NET "mcb4_dram_a[10]" IOSTANDARD = SSTL15_II; 74 | NET "mcb4_dram_a[11]" IOSTANDARD = SSTL15_II; 75 | NET "mcb4_dram_a[12]" IOSTANDARD = SSTL15_II; 76 | NET "mcb4_dram_a[13]" IOSTANDARD = SSTL15_II; 77 | NET "mcb4_dram_ba[0]" IOSTANDARD = SSTL15_II; 78 | NET "mcb4_dram_ba[1]" IOSTANDARD = SSTL15_II; 79 | NET "mcb4_dram_ba[2]" IOSTANDARD = SSTL15_II; 80 | NET "mcb4_dram_cas_n" IOSTANDARD = SSTL15_II; 81 | NET "mcb4_dram_ck" IOSTANDARD = DIFF_SSTL15_II; 82 | NET "mcb4_dram_ck_n" IOSTANDARD = DIFF_SSTL15_II; 83 | NET "mcb4_dram_cke" IOSTANDARD = SSTL15_II; 84 | NET "mcb4_dram_dm" IOSTANDARD = SSTL15_II; 85 | NET "mcb4_dram_dq[0]" IOSTANDARD = SSTL15_II; 86 | NET "mcb4_dram_dq[1]" IOSTANDARD = SSTL15_II; 87 | NET "mcb4_dram_dq[2]" IOSTANDARD = SSTL15_II; 88 | NET "mcb4_dram_dq[3]" IOSTANDARD = SSTL15_II; 89 | NET "mcb4_dram_dq[4]" IOSTANDARD = SSTL15_II; 90 | NET "mcb4_dram_dq[5]" IOSTANDARD = SSTL15_II; 91 | NET "mcb4_dram_dq[6]" IOSTANDARD = SSTL15_II; 92 | NET "mcb4_dram_dq[7]" IOSTANDARD = SSTL15_II; 93 | NET "mcb4_dram_dq[8]" IOSTANDARD = SSTL15_II; 94 | NET "mcb4_dram_dq[9]" IOSTANDARD = SSTL15_II; 95 | NET "mcb4_dram_dq[10]" IOSTANDARD = SSTL15_II; 96 | NET "mcb4_dram_dq[11]" IOSTANDARD = SSTL15_II; 97 | NET "mcb4_dram_dq[12]" IOSTANDARD = SSTL15_II; 98 | NET "mcb4_dram_dq[13]" IOSTANDARD = SSTL15_II; 99 | NET "mcb4_dram_dq[14]" IOSTANDARD = SSTL15_II; 100 | NET "mcb4_dram_dq[15]" IOSTANDARD = SSTL15_II; 101 | NET "mcb4_dram_dqs" IOSTANDARD = DIFF_SSTL15_II; 102 | NET "mcb4_dram_dqs_n" IOSTANDARD = DIFF_SSTL15_II; 103 | NET "mcb4_dram_odt" IOSTANDARD = SSTL15_II; 104 | NET "mcb4_dram_ras_n" IOSTANDARD = SSTL15_II; 105 | NET "mcb4_dram_reset_n" IOSTANDARD = SSTL15_II; 106 | NET "mcb4_dram_udm" IOSTANDARD = SSTL15_II; 107 | NET "mcb4_dram_udqs" IOSTANDARD = DIFF_SSTL15_II; 108 | NET "mcb4_dram_udqs_n" IOSTANDARD = DIFF_SSTL15_II; 109 | NET "mcb4_dram_we_n" IOSTANDARD = SSTL15_II; 110 | NET "mcb4_rzq" IOSTANDARD = SSTL15_II; 111 | NET "mcb4_zio" IOSTANDARD = SSTL15_II; 112 | NET "mcb5_dram_a[0]" IOSTANDARD = SSTL15_II; 113 | NET "mcb5_dram_a[1]" IOSTANDARD = SSTL15_II; 114 | NET "mcb5_dram_a[2]" IOSTANDARD = SSTL15_II; 115 | NET "mcb5_dram_a[3]" IOSTANDARD = SSTL15_II; 116 | NET "mcb5_dram_a[4]" IOSTANDARD = SSTL15_II; 117 | NET "mcb5_dram_a[5]" IOSTANDARD = SSTL15_II; 118 | NET "mcb5_dram_a[6]" IOSTANDARD = SSTL15_II; 119 | NET "mcb5_dram_a[7]" IOSTANDARD = SSTL15_II; 120 | NET "mcb5_dram_a[8]" IOSTANDARD = SSTL15_II; 121 | NET "mcb5_dram_a[9]" IOSTANDARD = SSTL15_II; 122 | NET "mcb5_dram_a[10]" IOSTANDARD = SSTL15_II; 123 | NET "mcb5_dram_a[11]" IOSTANDARD = SSTL15_II; 124 | NET "mcb5_dram_a[12]" IOSTANDARD = SSTL15_II; 125 | NET "mcb5_dram_a[13]" IOSTANDARD = SSTL15_II; 126 | NET "mcb5_dram_ba[0]" IOSTANDARD = SSTL15_II; 127 | NET "mcb5_dram_ba[1]" IOSTANDARD = SSTL15_II; 128 | NET "mcb5_dram_ba[2]" IOSTANDARD = SSTL15_II; 129 | NET "mcb5_dram_cas_n" IOSTANDARD = SSTL15_II; 130 | NET "mcb5_dram_ck" IOSTANDARD = DIFF_SSTL15_II; 131 | NET "mcb5_dram_ck_n" IOSTANDARD = DIFF_SSTL15_II; 132 | NET "mcb5_dram_cke" IOSTANDARD = SSTL15_II; 133 | NET "mcb5_dram_dm" IOSTANDARD = SSTL15_II; 134 | NET "mcb5_dram_dq[0]" IOSTANDARD = SSTL15_II; 135 | NET "mcb5_dram_dq[1]" IOSTANDARD = SSTL15_II; 136 | NET "mcb5_dram_dq[2]" IOSTANDARD = SSTL15_II; 137 | NET "mcb5_dram_dq[3]" IOSTANDARD = SSTL15_II; 138 | NET "mcb5_dram_dq[4]" IOSTANDARD = SSTL15_II; 139 | NET "mcb5_dram_dq[5]" IOSTANDARD = SSTL15_II; 140 | NET "mcb5_dram_dq[6]" IOSTANDARD = SSTL15_II; 141 | NET "mcb5_dram_dq[7]" IOSTANDARD = SSTL15_II; 142 | NET "mcb5_dram_dq[8]" IOSTANDARD = SSTL15_II; 143 | NET "mcb5_dram_dq[9]" IOSTANDARD = SSTL15_II; 144 | NET "mcb5_dram_dq[10]" IOSTANDARD = SSTL15_II; 145 | NET "mcb5_dram_dq[11]" IOSTANDARD = SSTL15_II; 146 | NET "mcb5_dram_dq[12]" IOSTANDARD = SSTL15_II; 147 | NET "mcb5_dram_dq[13]" IOSTANDARD = SSTL15_II; 148 | NET "mcb5_dram_dq[14]" IOSTANDARD = SSTL15_II; 149 | NET "mcb5_dram_dq[15]" IOSTANDARD = SSTL15_II; 150 | NET "mcb5_dram_dqs" IOSTANDARD = DIFF_SSTL15_II; 151 | NET "mcb5_dram_dqs_n" IOSTANDARD = DIFF_SSTL15_II; 152 | NET "mcb5_dram_odt" IOSTANDARD = SSTL15_II; 153 | NET "mcb5_dram_ras_n" IOSTANDARD = SSTL15_II; 154 | NET "mcb5_dram_reset_n" IOSTANDARD = SSTL15_II; 155 | NET "mcb5_dram_udm" IOSTANDARD = SSTL15_II; 156 | NET "mcb5_dram_udqs" IOSTANDARD = DIFF_SSTL15_II; 157 | NET "mcb5_dram_udqs_n" IOSTANDARD = DIFF_SSTL15_II; 158 | NET "mcb5_dram_we_n" IOSTANDARD = SSTL15_II; 159 | NET "mcb5_rzq" IOSTANDARD = SSTL15_II; 160 | NET "mcb5_zio" IOSTANDARD = SSTL15_II; 161 | NET "nFMC0_PRSNT" IOSTANDARD = LVCMOS33; 162 | NET "nFMC1_PRSNT" IOSTANDARD = LVCMOS33; 163 | NET "GPIO[0]" DRIVE = 24; 164 | NET "GPIO[1]" DRIVE = 24; 165 | NET "GPIO[2]" DRIVE = 24; 166 | NET "GPIO[3]" DRIVE = 24; 167 | NET "GPIO[4]" DRIVE = 24; 168 | NET "GPIO[5]" DRIVE = 24; 169 | NET "GPIO[6]" DRIVE = 24; 170 | NET "GPIO[7]" DRIVE = 24; 171 | NET "GPIO[8]" DRIVE = 24; 172 | NET "GPIO[9]" DRIVE = 24; 173 | NET "GPIO[10]" DRIVE = 24; 174 | NET "GPIO[11]" DRIVE = 24; 175 | NET "GPIO[12]" DRIVE = 24; 176 | NET "GPIO[13]" DRIVE = 24; 177 | NET "GPIO[14]" DRIVE = 24; 178 | NET "GPIO[15]" DRIVE = 24; 179 | NET "USER_LED[0]" DRIVE = 24; 180 | NET "USER_LED[1]" DRIVE = 24; 181 | NET "USER_LED[2]" DRIVE = 24; 182 | NET "USER_LED[3]" DRIVE = 24; 183 | NET "USER_LED[4]" DRIVE = 24; 184 | NET "USER_LED[5]" DRIVE = 24; 185 | NET "USER_LED[6]" DRIVE = 24; 186 | NET "USER_LED[7]" DRIVE = 24; 187 | NET "GIGE_GTX_CLK" SLEW = FAST; 188 | NET "GIGE_TXD[0]" SLEW = FAST; 189 | NET "GIGE_TXD[1]" SLEW = FAST; 190 | NET "GIGE_TXD[2]" SLEW = FAST; 191 | NET "GIGE_TXD[3]" SLEW = FAST; 192 | NET "GIGE_TXD[4]" SLEW = FAST; 193 | NET "GIGE_TXD[5]" SLEW = FAST; 194 | NET "GIGE_TXD[6]" SLEW = FAST; 195 | NET "GIGE_TXD[7]" SLEW = FAST; 196 | NET "GIGE_TX_EN" SLEW = FAST; 197 | NET "GIGE_TX_ER" SLEW = FAST; 198 | NET "CONF_CCLK" LOC = AE24; 199 | NET "CONF_DIN" LOC = AD23; 200 | NET "CONF_INIT_B" LOC = AE3; 201 | NET "FMC0_CLK0_M2C" LOC = W24; 202 | NET "FMC0_CLK1_M2C" LOC = U26; 203 | NET "FMC0_GA0" LOC = AA23; 204 | NET "FMC0_GA1" LOC = AA24; 205 | NET "FMC0_LA_N[0]" LOC = AF15; 206 | NET "FMC0_LA_N[1]" LOC = AC14; 207 | NET "FMC0_LA_N[2]" LOC = AA22; 208 | NET "FMC0_LA_N[3]" LOC = Y20; 209 | NET "FMC0_LA_N[4]" LOC = AC22; 210 | NET "FMC0_LA_N[5]" LOC = W19; 211 | NET "FMC0_LA_N[6]" LOC = W18; 212 | NET "FMC0_LA_N[7]" LOC = AB21; 213 | NET "FMC0_LA_N[8]" LOC = AA17; 214 | NET "FMC0_LA_N[9]" LOC = V16; 215 | NET "FMC0_LA_N[10]" LOC = AB19; 216 | NET "FMC0_LA_N[11]" LOC = Y16; 217 | NET "FMC0_LA_N[12]" LOC = AB17; 218 | NET "FMC0_LA_N[13]" LOC = AA16; 219 | NET "FMC0_LA_N[14]" LOC = V15; 220 | NET "FMC0_LA_N[15]" LOC = V13; 221 | NET "FMC0_LA_N[16]" LOC = AB15; 222 | NET "FMC0_LA_N[17]" LOC = AF13; 223 | NET "FMC0_LA_N[18]" LOC = AF14; 224 | NET "FMC0_LA_N[19]" LOC = AA12; 225 | NET "FMC0_LA_N[20]" LOC = Y13; 226 | NET "FMC0_LA_N[21]" LOC = W12; 227 | NET "FMC0_LA_N[22]" LOC = AA13; 228 | NET "FMC0_LA_N[23]" LOC = AA11; 229 | NET "FMC0_LA_N[24]" LOC = V10; 230 | NET "FMC0_LA_N[25]" LOC = AB9; 231 | NET "FMC0_LA_N[26]" LOC = AB11; 232 | NET "FMC0_LA_N[27]" LOC = AF6; 233 | NET "FMC0_LA_N[28]" LOC = W9; 234 | NET "FMC0_LA_N[29]" LOC = AF5; 235 | NET "FMC0_LA_N[30]" LOC = AA8; 236 | NET "FMC0_LA_N[31]" LOC = AC6; 237 | NET "FMC0_LA_N[32]" LOC = AD5; 238 | NET "FMC0_LA_N[33]" LOC = W7; 239 | NET "FMC0_LA_P[0]" LOC = AE15; 240 | NET "FMC0_LA_P[1]" LOC = AB14; 241 | NET "FMC0_LA_P[2]" LOC = Y21; 242 | NET "FMC0_LA_P[3]" LOC = W20; 243 | NET "FMC0_LA_P[4]" LOC = AB22; 244 | NET "FMC0_LA_P[5]" LOC = V18; 245 | NET "FMC0_LA_P[6]" LOC = W17; 246 | NET "FMC0_LA_P[7]" LOC = AA21; 247 | NET "FMC0_LA_P[8]" LOC = Y17; 248 | NET "FMC0_LA_P[9]" LOC = U15; 249 | NET "FMC0_LA_P[10]" LOC = AA19; 250 | NET "FMC0_LA_P[11]" LOC = W16; 251 | NET "FMC0_LA_P[12]" LOC = AA18; 252 | NET "FMC0_LA_P[13]" LOC = Y15; 253 | NET "FMC0_LA_P[14]" LOC = V14; 254 | NET "FMC0_LA_P[15]" LOC = U13; 255 | NET "FMC0_LA_P[16]" LOC = AA15; 256 | NET "FMC0_LA_P[17]" LOC = AE13; 257 | NET "FMC0_LA_P[18]" LOC = AD14; 258 | NET "FMC0_LA_P[19]" LOC = Y12; 259 | NET "FMC0_LA_P[20]" LOC = W14; 260 | NET "FMC0_LA_P[21]" LOC = V12; 261 | NET "FMC0_LA_P[22]" LOC = AB13; 262 | NET "FMC0_LA_P[23]" LOC = Y11; 263 | NET "FMC0_LA_P[24]" LOC = V11; 264 | NET "FMC0_LA_P[25]" LOC = AA9; 265 | NET "FMC0_LA_P[26]" LOC = AA10; 266 | NET "FMC0_LA_P[27]" LOC = AD6; 267 | NET "FMC0_LA_P[28]" LOC = W10; 268 | NET "FMC0_LA_P[29]" LOC = AE5; 269 | NET "FMC0_LA_P[30]" LOC = Y9; 270 | NET "FMC0_LA_P[31]" LOC = AB7; 271 | NET "FMC0_LA_P[32]" LOC = AC5; 272 | NET "FMC0_LA_P[33]" LOC = W8; 273 | NET "FMC0_ZDOK_N[0]" LOC = P8; 274 | NET "FMC0_ZDOK_N[1]" LOC = N4; 275 | NET "FMC0_ZDOK_N[2]" LOC = AA6; 276 | NET "FMC0_ZDOK_N[3]" LOC = AF4; 277 | NET "FMC0_ZDOK_P[0]" LOC = R9; 278 | NET "FMC0_ZDOK_P[1]" LOC = N5; 279 | NET "FMC0_ZDOK_P[2]" LOC = AA7; 280 | NET "FMC0_ZDOK_P[3]" LOC = AD4; 281 | NET "FMC1_CLK0_M2C" LOC = R6; 282 | NET "FMC1_CLK1_M2C" LOC = R1; 283 | NET "FMC1_GA0" LOC = U19; 284 | NET "FMC1_GA1" LOC = U20; 285 | NET "FMC1_LA_N[0]" LOC = D13; 286 | NET "FMC1_LA_N[1]" LOC = A13; 287 | NET "FMC1_LA_N[2]" LOC = G8; 288 | NET "FMC1_LA_N[3]" LOC = F6; 289 | NET "FMC1_LA_N[4]" LOC = B3; 290 | NET "FMC1_LA_N[5]" LOC = F5; 291 | NET "FMC1_LA_N[6]" LOC = E5; 292 | NET "FMC1_LA_N[7]" LOC = G9; 293 | NET "FMC1_LA_N[8]" LOC = A2; 294 | NET "FMC1_LA_N[9]" LOC = E8; 295 | NET "FMC1_LA_N[10]" LOC = C5; 296 | NET "FMC1_LA_N[11]" LOC = G10; 297 | NET "FMC1_LA_N[12]" LOC = A4; 298 | NET "FMC1_LA_N[13]" LOC = E10; 299 | NET "FMC1_LA_N[14]" LOC = A5; 300 | NET "FMC1_LA_N[15]" LOC = F11; 301 | NET "FMC1_LA_N[16]" LOC = E12; 302 | NET "FMC1_LA_N[17]" LOC = A12; 303 | NET "FMC1_LA_N[18]" LOC = G11; 304 | NET "FMC1_LA_N[19]" LOC = G13; 305 | NET "FMC1_LA_N[20]" LOC = J12; 306 | NET "FMC1_LA_N[21]" LOC = H13; 307 | NET "FMC1_LA_N[22]" LOC = E14; 308 | NET "FMC1_LA_N[23]" LOC = H14; 309 | NET "FMC1_LA_N[24]" LOC = H15; 310 | NET "FMC1_LA_N[25]" LOC = J17; 311 | NET "FMC1_LA_N[26]" LOC = E16; 312 | NET "FMC1_LA_N[27]" LOC = F15; 313 | NET "FMC1_LA_N[28]" LOC = E18; 314 | NET "FMC1_LA_N[29]" LOC = F17; 315 | NET "FMC1_LA_N[30]" LOC = E20; 316 | NET "FMC1_LA_N[31]" LOC = G17; 317 | NET "FMC1_LA_N[32]" LOC = B21; 318 | NET "FMC1_LA_N[33]" LOC = H19; 319 | NET "FMC1_LA_P[0]" LOC = E13; 320 | NET "FMC1_LA_P[1]" LOC = C13; 321 | NET "FMC1_LA_P[2]" LOC = H8; 322 | NET "FMC1_LA_P[3]" LOC = F7; 323 | NET "FMC1_LA_P[4]" LOC = C3; 324 | NET "FMC1_LA_P[5]" LOC = G6; 325 | NET "FMC1_LA_P[6]" LOC = E6; 326 | NET "FMC1_LA_P[7]" LOC = H9; 327 | NET "FMC1_LA_P[8]" LOC = A3; 328 | NET "FMC1_LA_P[9]" LOC = F9; 329 | NET "FMC1_LA_P[10]" LOC = D5; 330 | NET "FMC1_LA_P[11]" LOC = H10; 331 | NET "FMC1_LA_P[12]" LOC = B4; 332 | NET "FMC1_LA_P[13]" LOC = F10; 333 | NET "FMC1_LA_P[14]" LOC = B5; 334 | NET "FMC1_LA_P[15]" LOC = G12; 335 | NET "FMC1_LA_P[16]" LOC = F12; 336 | NET "FMC1_LA_P[17]" LOC = B12; 337 | NET "FMC1_LA_P[18]" LOC = J11; 338 | NET "FMC1_LA_P[19]" LOC = H12; 339 | NET "FMC1_LA_P[20]" LOC = K12; 340 | NET "FMC1_LA_P[21]" LOC = J13; 341 | NET "FMC1_LA_P[22]" LOC = F14; 342 | NET "FMC1_LA_P[23]" LOC = K14; 343 | NET "FMC1_LA_P[24]" LOC = J15; 344 | NET "FMC1_LA_P[25]" LOC = J16; 345 | NET "FMC1_LA_P[26]" LOC = F16; 346 | NET "FMC1_LA_P[27]" LOC = G15; 347 | NET "FMC1_LA_P[28]" LOC = F18; 348 | NET "FMC1_LA_P[29]" LOC = G16; 349 | NET "FMC1_LA_P[30]" LOC = F20; 350 | NET "FMC1_LA_P[31]" LOC = H17; 351 | NET "FMC1_LA_P[32]" LOC = C21; 352 | NET "FMC1_LA_P[33]" LOC = H18; 353 | NET "FMC1_ZDOK_N[0]" LOC = A22; 354 | NET "FMC1_ZDOK_N[1]" LOC = F19; 355 | NET "FMC1_ZDOK_N[2]" LOC = A23; 356 | NET "FMC1_ZDOK_N[3]" LOC = D22; 357 | NET "FMC1_ZDOK_P[0]" LOC = B22; 358 | NET "FMC1_ZDOK_P[1]" LOC = G19; 359 | NET "FMC1_ZDOK_P[2]" LOC = B23; 360 | NET "FMC1_ZDOK_P[3]" LOC = D21; 361 | NET "FMC_I2C_SCL" LOC = T20; 362 | NET "FMC_I2C_SDA" LOC = T19; 363 | NET "FPGA_AWAKE" LOC = AC23; 364 | NET "FPGA_PROC_BUS_A[1]" LOC = N17; 365 | NET "FPGA_PROC_BUS_A[2]" LOC = N18; 366 | NET "FPGA_PROC_BUS_A[3]" LOC = L23; 367 | NET "FPGA_PROC_BUS_A[4]" LOC = L24; 368 | NET "FPGA_PROC_BUS_A[5]" LOC = N19; 369 | NET "FPGA_PROC_BUS_A[6]" LOC = N20; 370 | NET "FPGA_PROC_BUS_A[7]" LOC = N21; 371 | NET "FPGA_PROC_BUS_A[8]" LOC = N22; 372 | NET "FPGA_PROC_BUS_A[9]" LOC = P17; 373 | NET "FPGA_PROC_BUS_A[10]" LOC = P19; 374 | NET "FPGA_PROC_BUS_BUSY0" LOC = AD26; 375 | NET "FPGA_PROC_BUS_BUSY1" LOC = AB24; 376 | NET "FPGA_PROC_BUS_CLK" LOC = R26; 377 | NET "FPGA_PROC_BUS_D[0]" LOC = N23; 378 | NET "FPGA_PROC_BUS_D[1]" LOC = N24; 379 | NET "FPGA_PROC_BUS_D[2]" LOC = R18; 380 | NET "FPGA_PROC_BUS_D[3]" LOC = R19; 381 | NET "FPGA_PROC_BUS_D[4]" LOC = P21; 382 | NET "FPGA_PROC_BUS_D[5]" LOC = P22; 383 | NET "FPGA_PROC_BUS_D[6]" LOC = R20; 384 | NET "FPGA_PROC_BUS_D[7]" LOC = R21; 385 | NET "FPGA_PROC_BUS_D[8]" LOC = P24; 386 | NET "FPGA_PROC_BUS_D[9]" LOC = P26; 387 | NET "FPGA_PROC_BUS_D[10]" LOC = R23; 388 | NET "FPGA_PROC_BUS_D[11]" LOC = R24; 389 | NET "FPGA_PROC_BUS_D[12]" LOC = T22; 390 | NET "FPGA_PROC_BUS_D[13]" LOC = T23; 391 | NET "FPGA_PROC_BUS_D[14]" LOC = U23; 392 | NET "FPGA_PROC_BUS_D[15]" LOC = R25; 393 | NET "FPGA_PROC_BUS_nADV_ALE" LOC = AA26; 394 | NET "FPGA_PROC_BUS_nCS0" LOC = V23; 395 | NET "FPGA_PROC_BUS_nCS1" LOC = U25; 396 | NET "FPGA_PROC_BUS_nCS2" LOC = T24; 397 | NET "FPGA_PROC_BUS_nCS3" LOC = T26; 398 | NET "FPGA_PROC_BUS_nCS4" LOC = V24; 399 | NET "FPGA_PROC_BUS_nCS5" LOC = V26; 400 | NET "FPGA_PROC_BUS_nCS6" LOC = W25; 401 | NET "FPGA_PROC_BUS_nOE" LOC = AA25; 402 | NET "FPGA_PROC_BUS_nWE" LOC = W26; 403 | NET "FPGA_PROC_BUS_nWP" LOC = AD24; 404 | NET "FP_I2C_SCL" LOC = AC26; 405 | NET "FP_I2C_SDA" LOC = AC25; 406 | NET "GIGE_COL" LOC = AC2; 407 | NET "GIGE_COMA" LOC = AA1; 408 | NET "GIGE_CRS" LOC = AD1; 409 | NET "GIGE_GTX_CLK" LOC = AB5; 410 | NET "GIGE_MDC" LOC = AC1; 411 | NET "GIGE_MDIO" LOC = AE2; 412 | NET "GIGE_RXD[0]" LOC = W5; 413 | NET "GIGE_RXD[1]" LOC = U9; 414 | NET "GIGE_RXD[2]" LOC = U8; 415 | NET "GIGE_RXD[3]" LOC = U7; 416 | NET "GIGE_RXD[4]" LOC = T6; 417 | NET "GIGE_RXD[5]" LOC = AB3; 418 | NET "GIGE_RXD[6]" LOC = AB1; 419 | NET "GIGE_RXD[7]" LOC = AD3; 420 | NET "GIGE_RX_CLK" LOC = W3; 421 | NET "GIGE_RX_DV" LOC = U3; 422 | NET "GIGE_RX_ER" LOC = V5; 423 | NET "GIGE_TXD[0]" LOC = AA3; 424 | NET "GIGE_TXD[1]" LOC = Y6; 425 | NET "GIGE_TXD[2]" LOC = Y5; 426 | NET "GIGE_TXD[3]" LOC = AB4; 427 | NET "GIGE_TXD[4]" LOC = AC3; 428 | NET "GIGE_TXD[5]" LOC = V7; 429 | NET "GIGE_TXD[6]" LOC = V6; 430 | NET "GIGE_TXD[7]" LOC = U4; 431 | NET "GIGE_TX_CLK" LOC = T1; 432 | NET "GIGE_TX_EN" LOC = AC4; 433 | NET "GIGE_TX_ER" LOC = AA4; 434 | NET "GIGE_nINT" LOC = AE1; 435 | NET "GIGE_nRESET" LOC = AA2; 436 | NET "GPIO[0]" LOC = R8; 437 | NET "GPIO[1]" LOC = T8; 438 | NET "GPIO[2]" LOC = U5; 439 | NET "GPIO[3]" LOC = T4; 440 | NET "GPIO[4]" LOC = R10; 441 | NET "GPIO[5]" LOC = T9; 442 | NET "GPIO[6]" LOC = P3; 443 | NET "GPIO[7]" LOC = P1; 444 | NET "GPIO[8]" LOC = N6; 445 | NET "GPIO[9]" LOC = P6; 446 | NET "GPIO[10]" LOC = P5; 447 | NET "GPIO[11]" LOC = R5; 448 | NET "GPIO[12]" LOC = N8; 449 | NET "GPIO[13]" LOC = N7; 450 | NET "GPIO[14]" LOC = R4; 451 | NET "GPIO[15]" LOC = R3; 452 | NET "IEEE1588_CLK" LOC = U24; 453 | NET "IEEE1588_GPIO[0]" LOC = AE25; 454 | NET "IEEE1588_GPIO[1]" LOC = AE26; 455 | NET "IEEE1588_GPIO[2]" LOC = U21; 456 | NET "IEEE1588_GPIO[3]" LOC = U22; 457 | NET "SYS_CLK_N" LOC = A14; 458 | NET "SYS_CLK_P" LOC = B14; 459 | NET "USER_LED[0]" LOC = Y3; 460 | NET "USER_LED[1]" LOC = Y1; 461 | NET "USER_LED[2]" LOC = W2; 462 | NET "USER_LED[3]" LOC = W1; 463 | NET "USER_LED[4]" LOC = V3; 464 | NET "USER_LED[5]" LOC = V1; 465 | NET "USER_LED[6]" LOC = U2; 466 | NET "USER_LED[7]" LOC = U1; 467 | NET "mcb4_dram_a[0]" LOC = L7; 468 | NET "mcb4_dram_a[1]" LOC = L6; 469 | NET "mcb4_dram_a[2]" LOC = K10; 470 | NET "mcb4_dram_a[3]" LOC = M8; 471 | NET "mcb4_dram_a[4]" LOC = J7; 472 | NET "mcb4_dram_a[5]" LOC = L4; 473 | NET "mcb4_dram_a[6]" LOC = L3; 474 | NET "mcb4_dram_a[7]" LOC = L10; 475 | NET "mcb4_dram_a[8]" LOC = C2; 476 | NET "mcb4_dram_a[9]" LOC = C1; 477 | NET "mcb4_dram_a[10]" LOC = J9; 478 | NET "mcb4_dram_a[11]" LOC = E3; 479 | NET "mcb4_dram_a[12]" LOC = K8; 480 | NET "mcb4_dram_a[13]" LOC = K7; 481 | NET "mcb4_dram_ba[0]" LOC = B2; 482 | NET "mcb4_dram_ba[1]" LOC = B1; 483 | NET "mcb4_dram_ba[2]" LOC = G3; 484 | NET "mcb4_dram_cas_n" LOC = L8; 485 | NET "mcb4_dram_ck" LOC = K5; 486 | NET "mcb4_dram_ck_n" LOC = J5; 487 | NET "mcb4_dram_cke" LOC = K9; 488 | NET "mcb4_dram_dm" LOC = J3; 489 | NET "mcb4_dram_dq[0]" LOC = H3; 490 | NET "mcb4_dram_dq[1]" LOC = H1; 491 | NET "mcb4_dram_dq[2]" LOC = G2; 492 | NET "mcb4_dram_dq[3]" LOC = G1; 493 | NET "mcb4_dram_dq[4]" LOC = D3; 494 | NET "mcb4_dram_dq[5]" LOC = D1; 495 | NET "mcb4_dram_dq[6]" LOC = E2; 496 | NET "mcb4_dram_dq[7]" LOC = E1; 497 | NET "mcb4_dram_dq[8]" LOC = J2; 498 | NET "mcb4_dram_dq[9]" LOC = J1; 499 | NET "mcb4_dram_dq[10]" LOC = K3; 500 | NET "mcb4_dram_dq[11]" LOC = K1; 501 | NET "mcb4_dram_dq[12]" LOC = M3; 502 | NET "mcb4_dram_dq[13]" LOC = M1; 503 | NET "mcb4_dram_dq[14]" LOC = N2; 504 | NET "mcb4_dram_dq[15]" LOC = N1; 505 | NET "mcb4_dram_dqs" LOC = F3; 506 | NET "mcb4_dram_dqs_n" LOC = F1; 507 | NET "mcb4_dram_odt" LOC = M6; 508 | NET "mcb4_dram_ras_n" LOC = L9; 509 | NET "mcb4_dram_reset_n" LOC = E4; 510 | NET "mcb4_dram_udm" LOC = J4; 511 | NET "mcb4_dram_udqs" LOC = L2; 512 | NET "mcb4_dram_udqs_n" LOC = L1; 513 | NET "mcb4_dram_we_n" LOC = G4; 514 | NET "mcb4_rzq" LOC = M4; 515 | NET "mcb4_zio" LOC = H6; 516 | NET "mcb5_dram_a[0]" LOC = C25; 517 | NET "mcb5_dram_a[1]" LOC = C26; 518 | NET "mcb5_dram_a[2]" LOC = E24; 519 | NET "mcb5_dram_a[3]" LOC = K21; 520 | NET "mcb5_dram_a[4]" LOC = G23; 521 | NET "mcb5_dram_a[5]" LOC = M18; 522 | NET "mcb5_dram_a[6]" LOC = M19; 523 | NET "mcb5_dram_a[7]" LOC = E23; 524 | NET "mcb5_dram_a[8]" LOC = H21; 525 | NET "mcb5_dram_a[9]" LOC = H22; 526 | NET "mcb5_dram_a[10]" LOC = F22; 527 | NET "mcb5_dram_a[11]" LOC = K19; 528 | NET "mcb5_dram_a[12]" LOC = C24; 529 | NET "mcb5_dram_a[13]" LOC = B24; 530 | NET "mcb5_dram_ba[0]" LOC = L19; 531 | NET "mcb5_dram_ba[1]" LOC = K20; 532 | NET "mcb5_dram_ba[2]" LOC = J22; 533 | NET "mcb5_dram_cas_n" LOC = G24; 534 | NET "mcb5_dram_ck" LOC = B25; 535 | NET "mcb5_dram_ck_n" LOC = B26; 536 | NET "mcb5_dram_cke" LOC = D23; 537 | NET "mcb5_dram_dm" LOC = J24; 538 | NET "mcb5_dram_dq[0]" LOC = G25; 539 | NET "mcb5_dram_dq[1]" LOC = G26; 540 | NET "mcb5_dram_dq[2]" LOC = H24; 541 | NET "mcb5_dram_dq[3]" LOC = H26; 542 | NET "mcb5_dram_dq[4]" LOC = E25; 543 | NET "mcb5_dram_dq[5]" LOC = E26; 544 | NET "mcb5_dram_dq[6]" LOC = D24; 545 | NET "mcb5_dram_dq[7]" LOC = D26; 546 | NET "mcb5_dram_dq[8]" LOC = K24; 547 | NET "mcb5_dram_dq[9]" LOC = K26; 548 | NET "mcb5_dram_dq[10]" LOC = J25; 549 | NET "mcb5_dram_dq[11]" LOC = J26; 550 | NET "mcb5_dram_dq[12]" LOC = L25; 551 | NET "mcb5_dram_dq[13]" LOC = L26; 552 | NET "mcb5_dram_dq[14]" LOC = N25; 553 | NET "mcb5_dram_dq[15]" LOC = N26; 554 | NET "mcb5_dram_dqs" LOC = F24; 555 | NET "mcb5_dram_dqs_n" LOC = F26; 556 | NET "mcb5_dram_odt" LOC = K22; 557 | NET "mcb5_dram_ras_n" LOC = F23; 558 | NET "mcb5_dram_reset_n" LOC = K18; 559 | NET "mcb5_dram_udm" LOC = J23; 560 | NET "mcb5_dram_udqs" LOC = M24; 561 | NET "mcb5_dram_udqs_n" LOC = M26; 562 | NET "mcb5_dram_we_n" LOC = J20; 563 | NET "mcb5_rzq" LOC = M21; 564 | NET "mcb5_zio" LOC = H20; 565 | NET "nFMC0_PRSNT" LOC = V20; 566 | NET "nFMC1_PRSNT" LOC = V21; 567 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | MyHDL-based FPGA DSP Toolflow 2 | README 3 | Gordon Inggs ("my name with a dot instead of the space"@gmail.com) 4 | 5 | Project Description 6 | =================== 7 | Watch this space! 8 | * 9 | 10 | Guide to Project Contents 11 | ========================= 12 | 1) Supporting - directory for utilities used to create/look at the data that might be used/created by the toolflow 13 | 1.1) DFT_Arithmetic_Model - a simple arithmetic model for performing a DFT using my flexible-radix DFT algorithm 14 | 15 | 2) Tooflow_Code - directory for the toolflow code, including the base Actor and Arc classes, as well as the base module development testbench scripts. 16 | 2.1) HDFT_Code - blocks and scripts for the new version of my flexible-radix FFT algorithm 17 | 2.2) Old_HDFT_Code - first iteration of the toolflow, used to implement my flexible-radix FFT algorithm which takes advantage of FPGA multipliers. 18 | 19 | 3) Platfroms - directory for platform-specific components of the toolflow 20 | 3.1) Rhino - utilities and components for the Reconfigurable Hardware for computatioN and radiO (Rhino) Platform (www.rhinoplatform.org) 21 | * 22 | 23 | Dependencies 24 | ============ 25 | 1) Python 26 | 2) MyHDL (www.myhdl.org) 27 | 3) Numpy 28 | 4) Matplotlib 29 | * 30 | 31 | Getting Started 32 | =============== 33 | Still getting going, so haven't made a proper egg and install script, etc. I'm a big believer in tutorials, so I should get those going sometime. 34 | 35 | That being said, its pretty straight-forward to use: 36 | 1) Make sure you have the dependencies installed 37 | 2) Copy the code in the Toolflow Code directory into the directory in which you intend to create your DSP system. 38 | 3) Import the various libraries as needed in your code. Look at the dev scripts for guidance as how to use the library. 39 | * 40 | 41 | Development Plan 42 | ================ 43 | 1) Fundemental Arc and Actor Classes - working in simulation, as well as conversion to Verilog. (done) 44 | 2) Developing Actors for flexible-radix DFT Algorithm (done) 45 | 3) Combining and testing DFT Algorithm Actors into an implementation of the flexible-radix DFT algorithm. (pending) 46 | 4) Developing Rhino Gateware Framework - combination of MyHDL and HDL for testing converted graphs on the Rhino Platform (www.rhinoplatform.org) (planned) 47 | * 48 | -------------------------------------------------------------------------------- /Supporting/DFT_Arithmetic_Model/DFT_Model.py: -------------------------------------------------------------------------------- 1 | #Scalable Hybrid FFT-DFT Sequential Model 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #February 2011 5 | import sys, numpy, math, random, time 6 | from myhdl import intbv 7 | 8 | class HybridFFTDFT: 9 | #Public Variables 10 | input_file = "" 11 | samp_freq = 0 12 | output_file = "" 13 | input_bits = 0 14 | twiddle_bits = 0 15 | dft_size = 0 16 | dft_bits = 0 17 | output_bits = 0 18 | 19 | #Private Variables 20 | input_values_real = [] 21 | input_values_imag = [] 22 | output_values_real = [] 23 | output_values_imag = [] 24 | num_stages = 0 25 | subarrays_real = [] 26 | subarrays_imag = [] 27 | dft_real = [] 28 | dft_imag = [] 29 | 30 | def __init__(self,i_f,o_f,i_b,t_b,d_s,d_b,o_b): 31 | self.input_file = i_f 32 | self.output_file = o_f 33 | self.input_bits = i_b 34 | self.twiddle_bits = t_b 35 | self.dft_size = d_s 36 | self.dft_bits = d_b 37 | self.output_bits = o_b 38 | 39 | self.input_values_real = [] 40 | self.input_values_imag = [] 41 | self.input_values_real = [] 42 | self.input_values_imag = [] 43 | self.output_values_real = [] 44 | self.output_values_imag = [] 45 | self.num_stages = 0 46 | self.subarrays_real = [] 47 | self.subarrays_imag = [] 48 | self.dft_real = [] 49 | self.dft_imag = [] 50 | 51 | def twiddle_factors(self,N,stage_length,bits): 52 | """Method for generating twiddle factors for a particular stage of the butterfly or DAC""" 53 | segments = 2*numpy.pi/N 54 | stage = numpy.log(N/stage_length)/numpy.log(2) #Calculating which stage of the divide and conquer operation this is 55 | 56 | Wn_real = numpy.cos(segments) 57 | Wn_imag = -1*numpy.sin(segments) 58 | 59 | tf_real = [] 60 | tf_imag = [] 61 | for i in range(stage_length): #For the length of the stage, each twiddle factor is calculated 62 | value = (Wn_real+1.0j*Wn_imag)**(i*2**(stage-1)) 63 | if(bits): #scaling the twiddle factors 64 | value_real = int(value.real*(2**(bits-1))) 65 | value_imag = int(value.imag*(2**(bits-1))) 66 | 67 | if((value_real>=2**(bits-1)) and (value_imag>=2**(bits-1))): 68 | tf_real.append(intbv(value_real-1,min=-2**(bits-1),max=2**(bits-1))) 69 | tf_imag.append(intbv(value_imag-1,min=-2**(bits-1),max=2**(bits-1))) 70 | 71 | elif(value_real>=2**(bits-1)): 72 | tf_real.append(intbv(value_real-1,min=-2**(bits-1),max=2**(bits-1))) 73 | tf_imag.append(intbv(value_imag,min=-2**(bits-1),max=2**(bits-1))) 74 | 75 | elif(value_imag>=2**(bits-1)): 76 | tf_real.append(intbv(value_real,min=-2**(bits-1),max=2**(bits-1))) 77 | tf_imag.append(intbv(value_imag-1,min=-2**(bits-1),max=2**(bits-1))) 78 | 79 | else: 80 | tf_real.append(intbv(value_real,min=-2**(bits-1),max=2**(bits-1))) 81 | tf_imag.append(intbv(value_imag,min=-2**(bits-1),max=2**(bits-1))) 82 | 83 | else: 84 | value_real = value.real 85 | value_imag = value.imag 86 | 87 | tf_real.append(value_real) 88 | tf_imag.append(value_imag) 89 | 90 | return [tf_real,tf_imag] #list of twiddle factors is returned 91 | 92 | def twiddle_factors_power(self,size,bits): 93 | """Another method for generating twiddle factors, this time for the direct DFT""" 94 | segment_size = 2*numpy.pi/size 95 | base = numpy.cos(segment_size)-1.0j*(numpy.sin(segment_size)) 96 | 97 | tf_power_real = [] 98 | tf_power_imag = [] 99 | for i in range(size): 100 | tf_power_real.append([]) 101 | tf_power_imag.append([]) 102 | 103 | for n in range(size): 104 | value = base**(i*n) 105 | value_real = value.real 106 | value_imag = value.imag 107 | 108 | if(bits): #scaling the twiddle factors 109 | value_real = int(value_real*2**(bits-1)) 110 | value_imag = int(value_imag*2**(bits-1)) 111 | 112 | if((value_real>=2**(bits-1)) and (value_imag>=2**(bits-1))): 113 | value_real = intbv(value_real-1,min=-2**(bits-1),max=2**(bits-1)) 114 | value_imag = intbv(value_imag-1,min=-2**(bits-1),max=2**(bits-1)) 115 | 116 | elif(value_real>=2**(bits-1)): 117 | value_real = intbv(value_real-1,min=-2**(bits-1),max=2**(bits-1)) 118 | value_imag = intbv(value_imag,min=-2**(bits-1),max=2**(bits-1)) 119 | 120 | elif(value_imag>=2**(bits-1)): 121 | value_real = intbv(value_real,min=-2**(bits-1),max=2**(bits-1)) 122 | value_imag = intbv(value_imag-1,min=-2**(bits-1),max=2**(bits-1)) 123 | 124 | else: 125 | value_real = intbv(value_real,min=-2**(bits-1),max=2**(bits-1)) 126 | value_imag = intbv(value_imag,min=-2**(bits-1),max=2**(bits-1)) 127 | 128 | tf_power_real[-1].append(value_real) 129 | tf_power_imag[-1].append(value_imag) 130 | 131 | 132 | return [tf_power_real,tf_power_imag] 133 | 134 | def DFT(self): 135 | """Method for performing the direct DFT""" 136 | segments = 2*numpy.pi/self.dft_size #Calculating Twiddle Factors for DFT 137 | Wn_real = numpy.cos(segments) 138 | Wn_imag = -1.0*numpy.sin(segments) 139 | 140 | tf_power = self.twiddle_factors_power(self.dft_size,self.dft_bits) 141 | tf_power_real = tf_power[0] 142 | tf_power_imag = tf_power[1] 143 | 144 | for data in range(len(self.subarrays_real)): 145 | self.dft_real.append([]) 146 | self.dft_imag.append([]) 147 | 148 | for w in range(self.dft_size): 149 | temp_real = 0.0 150 | temp_imag = 0.0 151 | 152 | dft_bound = 1 153 | if(self.dft_bits): #checking if DFT has a set input bitsize 154 | dft_bound = 2**(2*self.dft_bits+self.dft_size-1) 155 | 156 | temp_real = intbv(0,min=-dft_bound,max=dft_bound) 157 | temp_imag = intbv(0,min=-dft_bound,max=dft_bound) 158 | 159 | if(self.output_bits): 160 | real_overflow_tracking = 2*self.dft_bits+int(self.dft_size/32.0) 161 | imag_overflow_tracking = 2*self.dft_bits+int(self.dft_size/32.0) 162 | overflow_flag = False 163 | 164 | 165 | for d in range(self.dft_size): #Inner loop of DFT 166 | input_value_real_scaled = self.subarrays_real[data][d] 167 | input_value_imag_scaled = self.subarrays_imag[data][d] 168 | 169 | 170 | if(self.twiddle_bits): 171 | dc_bound = 2**(self.twiddle_bits*(self.num_stages-1)+self.input_bits-1) #Bit size for input data for DFT - input_bitwidth + twiddle_factor_bitwidth*number_stages 172 | scaling_factor = (2.0**(self.dft_bits-1))/dc_bound #scaling factor for input to DFT = (DFT input size)/(D&C output bound) 173 | dc_bound = 2**(self.twiddle_bits*(self.num_stages-1)+self.input_bits-1) #Bit size for input data for DFT - input_bitwidth + )twiddle_factor_bitwidth*number_stages-1) 174 | scaling_factor = (2.0**(self.dft_bits-1))/dc_bound #scaling factor for input to DFT = (DFT input size)/(D&C output bound) 175 | 176 | if(((self.twiddle_bits*(self.num_stages-1)+self.input_bits-1)-(self.dft_bits-1)) >=0 ): 177 | input_value_real_scaled = (self.subarrays_real[data][d] >> ((self.twiddle_bits*(self.num_stages-1)+self.input_bits-1)-(self.dft_bits-1))) 178 | input_value_imag_scaled = (self.subarrays_imag[data][d] >> ((self.twiddle_bits*(self.num_stages-1)+self.input_bits-1)-(self.dft_bits-1))) 179 | else: 180 | input_value_real_scaled = self.subarrays_real[data][d] 181 | input_value_imag_scaled = self.subarrays_imag[data][d] 182 | 183 | value = (input_value_real_scaled +1.0j*input_value_imag_scaled)*(tf_power_real[w][d]+1.0j*tf_power_imag[w][d]) 184 | 185 | temp_real += int(value.real) 186 | temp_imag += int(value.imag) 187 | 188 | 189 | if(self.output_bits): #Checking to see if an overflow has occurred 190 | if(temp_real>(2**(real_overflow_tracking-1))): 191 | overflow_flag = True 192 | real_overflow_tracking += 1 193 | 194 | if(temp_imag>(2**(imag_overflow_tracking-1))): 195 | overflow_flag = True 196 | imag_overflow_tracking += 1 197 | 198 | if(temp_real<-(2**(2*self.dft_bits-1))): 199 | temp_real = temp_real/2 200 | 201 | if(temp_imag<-(2**(2*self.dft_bits-1))): 202 | temp_imag = temp_imag/2 203 | 204 | 205 | overflow_flag = False 206 | value_bits = 0 207 | if(self.output_bits): #Checking to see if an overflow has occurred 208 | if(temp_real>(2**(real_overflow_tracking-1))): 209 | overflow_flag = True 210 | real_overflow_tracking += 1 211 | 212 | if(temp_imag>(2**(imag_overflow_tracking-1))): 213 | overflow_flag = True 214 | imag_overflow_tracking += 1 215 | 216 | if(temp_real<-(2**(real_overflow_tracking-1))): 217 | overflow_flag = True 218 | real_overflow_tracking += 1 219 | 220 | if(temp_imag<-(2**(imag_overflow_tracking-1))): 221 | overflow_flag = True 222 | imag_overflow_tracking += 1 223 | 224 | temp_real_scaled = temp_real 225 | temp_imag_scaled = temp_imag 226 | 227 | 228 | if(self.output_bits): 229 | output_bound = 2**(self.output_bits) #Output bit size 230 | real_scaling_factor = 1.0*output_bound/(2**(real_overflow_tracking)) #scaling factor for output from DFT = output bit size / (output bit size from DFT, as tracked by overflow monitor variable) 231 | imag_scaling_factor = 1.0*output_bound/(2**(imag_overflow_tracking)) #scaling factor for output from DFT = output bit size / (output bit size from DFT, as tracked by overflow monitor variable) 232 | 233 | if(((2*self.dft_bits+int(self.dft_size/16.0))-self.output_bits)>=0): 234 | temp_real_scaled = intbv(int(temp_real_scaled >> ((2*self.dft_bits+int(self.dft_size/16.0))-self.output_bits)),min=-output_bound,max=output_bound) 235 | temp_imag_scaled = intbv(int(temp_imag_scaled >> ((2*self.dft_bits+int(self.dft_size/16.0))-self.output_bits)),min=-output_bound,max=output_bound) 236 | 237 | self.dft_real[-1].append(temp_real_scaled) 238 | self.dft_imag[-1].append(temp_imag_scaled) 239 | 240 | 241 | def readdata(self): 242 | """Method for reading input data from file""" 243 | input_bound = 2**(self.input_bits-1) 244 | 245 | source_data = (self.input_file.read()).split("\n")[:-1] 246 | if(input_bound>0.5): 247 | for sd in source_data: 248 | temp_val = sd.split(" ") 249 | self.input_values_real.append(intbv(int(temp_val[0]),min=-input_bound,max=(input_bound))) 250 | self.input_values_imag.append(intbv(int(temp_val[1]),min=-input_bound,max=(input_bound))) 251 | else: 252 | for sd in source_data: 253 | temp_val = sd.split(" ") 254 | self.input_values_real.append(float(temp_val[0])) 255 | self.input_values_imag.append(float(temp_val[1])) 256 | 257 | ##print len(self.input_values_real) 258 | self.num_stages = int(numpy.ceil(numpy.log(len(self.input_values_real)/self.dft_size)/numpy.log(2)))+1 #Calculating number of stages required 259 | ##print numpy.shape(self.input_values_real) 260 | 261 | def divide_and_conquer(self): 262 | """Method for performing divide and conquer operations""" 263 | self.subarrays_real = [self.input_values_real] #Starting out with the complete signal 264 | self.subarrays_imag = [self.input_values_imag] 265 | bits = (self.input_bits) 266 | 267 | for i in range(1,self.num_stages): #Loop for each stage 268 | bits += self.twiddle_bits #bound grows for each stage by the size of twiddle factors (twiddle bits -1) + 1 (in case of overflow) 269 | dc_bound = 2**(bits-1) 270 | stage_length = len(self.input_values_real)/(2**i) #Calculating the length of the subarrays at this length 271 | 272 | temp_real = [] 273 | temp_imag = [] 274 | for subset in range(len(self.subarrays_real)): #Breakdown of each subarray into two further subarrays 275 | upper_real = self.subarrays_real[subset][:stage_length] #splitting subarray into upper and lower parts of butterfly 276 | upper_imag = self.subarrays_imag[subset][:stage_length] 277 | 278 | lower_real = self.subarrays_real[subset][stage_length:] 279 | lower_imag = self.subarrays_imag[subset][stage_length:] 280 | 281 | temp_real.append([]) 282 | temp_imag.append([]) 283 | 284 | for j in range(len(upper_real)): 285 | value_real = (upper_real[j]+lower_real[j]) 286 | value_imag = (upper_imag[j]+lower_imag[j]) 287 | 288 | if(self.twiddle_bits): 289 | value_real = int(value_real*2**(self.twiddle_bits-1)) 290 | value_imag = int(value_imag*2**(self.twiddle_bits-1)) 291 | 292 | if((value_real>=dc_bound) and (value_imag>=dc_bound)): 293 | value_real = value_real-1 294 | value_imag = value_imag-1 295 | 296 | elif(value_real>=dc_bound): 297 | value_real = value_real-1 298 | 299 | elif(value_imag>=dc_bound): 300 | value_imag = value_imag-1 301 | 302 | temp_real[-1].append(intbv(value_real,min=-dc_bound,max=dc_bound))#upper branch of butterfly is only addition 303 | temp_imag[-1].append(intbv(value_imag,min=-dc_bound,max=dc_bound)) 304 | 305 | else: 306 | temp_real[-1].append(value_real) 307 | temp_imag[-1].append(value_imag) 308 | 309 | temp_tf = self.twiddle_factors(len(self.input_values_real),stage_length,self.twiddle_bits) #twiddle factors needed for lower butterfly 310 | 311 | temp_sub_real = [] 312 | temp_sub_imag = [] 313 | temp_real.append([]) 314 | temp_imag.append([]) 315 | for j in range(len(lower_real)): 316 | temp_sub_real.append(upper_real[j]-lower_real[j])#lower branch of butterfly is subtraction 317 | temp_sub_imag.append(upper_imag[j]-lower_imag[j]) 318 | 319 | value = (temp_sub_real[j]+1.0j*temp_sub_imag[j])*(temp_tf[0][j]+1.0j*temp_tf[1][j]) #Multiplication by twiddle factors 320 | 321 | if(self.twiddle_bits): 322 | temp_real[-1].append(int(value.real)) 323 | temp_imag[-1].append(int(value.imag)) 324 | 325 | else: 326 | temp_real[-1].append(value.real) 327 | temp_imag[-1].append(value.imag) 328 | 329 | self.subarrays_real = temp_real #the subarrays replace the larger subsets 330 | self.subarrays_imag = temp_imag 331 | 332 | 333 | def unscramble(self): 334 | """Method for undoing the decimation caused by the divide and conquer operations""" 335 | for d in self.dft_real: self.output_values_real.extend(d) 336 | for d in self.dft_imag: self.output_values_imag.extend(d) 337 | ui = range(len(self.output_values_real)) 338 | 339 | N_D = len(self.input_values_real)/self.dft_size #Number of DFTs performed for a particular stage, starting with the final stage 340 | D_S = self.dft_size #The size of a DFT performed for a particular stage 341 | bound = 2**(self.output_bits-1) 342 | 343 | for k in range(self.num_stages-1): #For each stage of decimation 344 | temp_ui = [0.0]*len(self.output_values_real) 345 | temp_real = [0.0]*len(self.output_values_real) #Creating temp list for placing the unscrambled data into 346 | temp_imag = [0.0]*len(self.output_values_imag) 347 | if(self.twiddle_bits): 348 | temp_real = [intbv(0,min=-bound,max=bound)]*len(self.output_values_real) #Creating temp list for placing the unscrambled data into 349 | temp_imag = [intbv(0,min=-bound,max=bound)]*len(self.output_values_imag) 350 | 351 | for i in range(N_D/2): #Iterating over the data in this stage of decimation 352 | start = i*D_S*2 #start and finish values are not rearranged, and so are copied straight across 353 | finish = i*D_S*2 + D_S*2-1 354 | 355 | temp_real[start] = self.output_values_real[start] 356 | temp_imag[start] = self.output_values_imag[start] 357 | temp_ui[start] = ui[start] 358 | 359 | temp_real[finish] = self.output_values_real[finish] 360 | temp_imag[finish] = self.output_values_imag[finish] 361 | temp_ui[finish] = ui[finish] 362 | 363 | upper = start+1 #starting point for the upper and lower branches of the rearrangement operation are calculated 364 | lower = start+D_S 365 | 366 | index = start+1 367 | for j in range(D_S-1): #Iterating over the remaining data in this stage of decimation, and assigning values to the correct part of the dataset 368 | temp_real[index] = self.output_values_real[lower] #lower values are first, then the upper value 369 | temp_imag[index] = self.output_values_imag[lower] 370 | temp_ui[index] = ui[lower] 371 | 372 | temp_real[index+1] = self.output_values_real[upper] 373 | temp_imag[index+1] = self.output_values_imag[upper] 374 | temp_ui[index+1] = ui[upper] 375 | 376 | index += 2 #indices are iterated 377 | lower += 1 378 | upper += 1 379 | 380 | self.output_values_real = temp_real #copy the unscrambled data to the output array 381 | self.output_values_imag = temp_imag 382 | ui = temp_ui 383 | 384 | D_S = D_S*2 #Increase the size of the "DFT" for the next stage of decimation reversal 385 | N_D = N_D/2 #Half the number of DFTs performed 386 | 387 | ##print ui 388 | 389 | def writedata(self): 390 | for i in range(len(self.output_values_real)): 391 | if(self.twiddle_bits):self.output_file.write("%d %d\n"% (self.output_values_real[i],self.output_values_imag[i])) 392 | else: self.output_file.write("%f %f\n"% (self.output_values_real[i],self.output_values_imag[i])) 393 | 394 | if __name__ == "__main__": 395 | print "Scalable DFT-FFT sequential model" 396 | print "usage: python DFT_Model.py [input filename] [output filename] [input bit width] [twiddle factor bit width] [DFT Size] [Multiplier input bit width] [Output bit width]" 397 | 398 | input_file = open(sys.argv[1]) 399 | output_file = open(sys.argv[2],"w") 400 | input_bits = int(sys.argv[3]) 401 | twiddle_bits = int(sys.argv[4]) 402 | dft_size = int(sys.argv[5]) 403 | dft_bits = int(sys.argv[6]) 404 | output_bits = int(sys.argv[7]) 405 | 406 | hfd = HybridFFTDFT(input_file,output_file,input_bits,twiddle_bits,dft_size,dft_bits,output_bits) 407 | print "Reading data" 408 | hfd.readdata() 409 | print "Dividing up data" 410 | hfd.divide_and_conquer() 411 | print "DFTing" 412 | hfd.DFT() 413 | print "Unscrambling" 414 | hfd.unscramble() 415 | print "Writing data" 416 | hfd.writedata() 417 | -------------------------------------------------------------------------------- /Supporting/complex_signal_file_generator.py: -------------------------------------------------------------------------------- 1 | #Signal File Generator Script 2 | #Rhino Project Toolflow 3 | #Gordon Inggs 4 | #January 2010 5 | import sys,numpy,matplotlib.pyplot as plt,math 6 | 7 | print "Complex Signal Generator Script" 8 | if len(sys.argv)<8: 9 | print "usage: python complex_signal_file_generator.py [base frequency] [rate of increase] [sampling frequency] [length (in seconds)] [output file name] [waveform type] [Bit Width]" 10 | print "waveform types: linear_chirp, white_noise, sine" 11 | 12 | else: 13 | print "reading in data" 14 | base_freq = float(sys.argv[1]) 15 | rate_increase = float(sys.argv[2]) 16 | samp_freq = float(sys.argv[3]) 17 | length = float(sys.argv[4]) 18 | output_file = open(sys.argv[5],"w") 19 | waveform = sys.argv[6] 20 | max_value = 2**(int(sys.argv[7])-1) 21 | if (max_value <= 0.5): max_value = 0 22 | 23 | num_samples = int(length*samp_freq) 24 | output_data = [0]*num_samples 25 | 26 | if(waveform=="linear_chirp"): 27 | print "generating linear chirp" 28 | max_freq = base_freq+num_samples/samp_freq*rate_increase 29 | if(max_freq > samp_freq/2): 30 | rate_increase = int(2*samp_freq/num_samples*(samp_freq**2/2-base_freq)) 31 | print "rate of increase constricted to %d to avoid aliasing" % length 32 | 33 | for n in range(num_samples): 34 | temp_freq = base_freq+rate_increase*n/samp_freq 35 | output_data[n] = numpy.sin(2.0*numpy.pi*(temp_freq)*n/samp_freq) 36 | 37 | elif(waveform=="white_noise"): 38 | print "generating noise" 39 | for n in range(num_samples): output_data[n] = math.floor(numpy.random.rand()*2-1) 40 | #print ("%d - %d" % (n,output_data[n])) 41 | 42 | elif(waveform=="sine"): 43 | print "generating sine wave" 44 | for n in range(num_samples): output_data[n] = numpy.sin(2.0*numpy.pi*(base_freq)*n/samp_freq) 45 | 46 | if(max_value): output_data = map(int,map(math.floor,numpy.array(output_data)*max_value)) 47 | 48 | if (max_value): 49 | for ov in output_data: 50 | if(ov==max_value): ov = ov-1 51 | output_file.write("%d %d\n"% (ov,0)) 52 | 53 | else: 54 | for ov in output_data: 55 | if(ov==max_value): ov = ov-1 56 | output_file.write("%f %f\n"% (ov,0.0)) 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Supporting/dft_error_analysis.py: -------------------------------------------------------------------------------- 1 | #Hybrid DFT Error Analysis Script 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #February 2011 5 | 6 | import sys,DFT_Model,numpy,matplotlib.pyplot as plt 7 | 8 | print "Frequency Spectrum Error Analysis Script" 9 | if (len(sys.argv)<2): print "usage: python dft_error_analysis.py [input file] [DFT Max index] [Output bit max]" 10 | 11 | else: 12 | input_file = open(sys.argv[1]) 13 | values = range(int(sys.argv[2]))[3:] 14 | 15 | errordata = [] 16 | msedata = [] 17 | dftvalues = [] 18 | for v in values: 19 | #variables for experiment 20 | output_file = open("tempdata/temp.dat","w") 21 | input_bits = 8 22 | twiddle_bits = 0 23 | dft_size = 2 24 | output_bits = 2**v 25 | dftvalues.append(output_bits) 26 | dft_bits = 0 27 | sample_rate = 1000 28 | print "%d output bits" % output_bits 29 | 30 | d = DFT_Model.HybridFFTDFT(input_file,output_file,input_bits,twiddle_bits,dft_size,dft_bits,output_bits) #setting up algorithm 31 | d.readdata() 32 | 33 | tempdata = [] 34 | for j in range(len(d.input_values_real)): tempdata.append((d.input_values_real[j]) + 1.0j*(d.input_values_imag[j])) 35 | 36 | tempdata = (numpy.fft).fft(tempdata) #reference FFT data 37 | 38 | refdata = [] 39 | for t in tempdata: 40 | refdata.append(abs(t)) 41 | 42 | tempdata = [] 43 | for r in refdata: 44 | tempdata.append(r/max(refdata)) #calculating the power and normalising reference FFT 45 | 46 | refdata = tempdata 47 | 48 | d.twiddle_bits = 8 49 | d.output_bits = 2**v 50 | d.dft_bits = 18 51 | msedata.append([]) 52 | 53 | #for loop that varies the size of the direct DFT used in the algorithm 54 | for i in range(1,int(sys.argv[3])): 55 | d.dft_real = [] 56 | d.dft_imag = [] 57 | d.output_values_real = [] 58 | d.output_values_imag = [] 59 | d.subarrays_real = [] 60 | d.subarrays_imag = [] 61 | d.dft_size = 2**i 62 | 63 | d.readdata() #performing the DFT using fixed point model 64 | d.divide_and_conquer() 65 | d.DFT() 66 | d.unscramble() 67 | 68 | output_values_real = d.output_values_real 69 | output_values_imag = d.output_values_imag 70 | 71 | output_bound = 2**(d.output_bits-1) 72 | testdata = [] 73 | for j in range(len(d.output_values_real)): testdata.append(abs(1.0*output_values_real[j]+ 1.0j*output_values_imag[j])) #calculating the magnitude 74 | 75 | refdata_range = max(refdata) - min(refdata) 76 | testdata_range = max(testdata) - min(testdata) 77 | 78 | tempdata = [] 79 | for t in testdata: tempdata.append(t/max(testdata)) #normalising testdata 80 | testdata = tempdata 81 | 82 | testdata_range = max(testdata) - min(testdata) 83 | 84 | mse = [] 85 | for j in range(len(testdata)): 86 | if(max(testdata)): mse.append((1.0*testdata[j]-1.0*refdata[j])**2.0) #calculating the square of the error 87 | 88 | msedata[-1].append(numpy.mean(mse)**0.5) #taking the root of the mean square error 89 | print "dft of size %d:\t\t\t\t%.16f" % (2**i,msedata[-1][-1]) 90 | 91 | outputdata = open("error_analysis/mse_dftsize.dat","w") 92 | outputbitvalues = [] 93 | for i in range(1,int(sys.argv[3])): outputbitvalues.append(2**i) 94 | 95 | for m in msedata: 96 | for d in m: outputdata.write("%.10f "%d) 97 | outputdata.write("\n") 98 | 99 | fig = plt.figure() #plotting results 100 | ax = fig.add_subplot(1,1,1) 101 | 102 | output_bits = 3 103 | for m in msedata: 104 | ax.plot(outputbitvalues,m,'-o',label="%d output bit size"%(2**output_bits)) 105 | output_bits +=1 106 | 107 | plt.title("RMSE vs DFT Size for Hybrid DFT Algorithm") 108 | plt.legend(loc="upper right") 109 | plt.show() -------------------------------------------------------------------------------- /Supporting/frequency_spectrum_viewer.py: -------------------------------------------------------------------------------- 1 | #Time Signal File Viewer Script 2 | #Rhino Project Toolflow 3 | #Gordon Inggs 4 | #December 2010 5 | import sys,numpy,matplotlib.pyplot as plt 6 | 7 | print "Frequency Viewer Script" 8 | if (len(sys.argv)<3): print "usage: python frequency_spectrum_viwer.py \"[input file1],[input_file_2],etc.\" \"[sampling frequency 1],[sampling frequency 2]\"" 9 | 10 | else: 11 | #Reading in Input Data 12 | input_files=[] 13 | for s in sys.argv[1].split(","): input_files.append(open(s)) 14 | samp_freqs = [] 15 | for s in sys.argv[2].split(","): samp_freqs.append(int(s)) 16 | 17 | fig = 1 18 | input_datasets = [] 19 | for i_f in input_files: 20 | source_data = (i_f.read()).split("\n")[:-1] 21 | input_datasets.append([]) 22 | for sd in source_data: 23 | temp_val = sd.split(" ") 24 | input_datasets[-1].append(float(temp_val[0]) + 1.0j*float(temp_val[1])) 25 | 26 | input_data = numpy.array(input_datasets[-1]) 27 | 28 | print "Data read in successfully from %s" % i_f.name 29 | print "%d data points present" % len(input_data) 30 | print "Signal Power Max = %d" % max(input_data**2) 31 | print "Signal Power Min = %d" % min(input_data**2) 32 | print "Signal Power Mean = %d\n" % (sum(input_data**2)/len(input_data)) 33 | 34 | plt.figure(fig) 35 | fig += 1 36 | plt.title(i_f.name) 37 | samp_freq = samp_freqs[fig-2] 38 | 39 | temp_data = [] 40 | for i_d in input_data: temp_data.append((i_d.real**2+i_d.imag**2)**0.5) #calculating the magnitude 41 | input_data = temp_data 42 | 43 | plot_data = list(input_data[len(input_data)/2:]) #rotating the DFT 44 | plot_data.extend(list(input_data[:len(input_data)/2])) 45 | x_axis = [] 46 | for x in range(-len(plot_data)/2,len(plot_data)/2): x_axis.append(x*samp_freq/len(input_data)) #creating frequency labels 47 | plot_data = 10*numpy.log(numpy.array(plot_data)/max(numpy.array(plot_data)))/numpy.log(10) 48 | 49 | plt.plot(x_axis,plot_data,'-o') 50 | 51 | plt.show() -------------------------------------------------------------------------------- /Toolflow_Code/Actor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | Actor Base Class 4 | 5 | Created on 22 Dec 2011 6 | 7 | @author: Gordon Inggs 8 | ''' 9 | from myhdl import * 10 | import Arc 11 | 12 | class Actor: 13 | name = "Actor" 14 | 15 | input_a = None#Arc.Arc(0,0,0,0,False,0) 16 | 17 | output_a = None#Arc.Arc(0,0,0,0,False,0) 18 | 19 | scale = 1 20 | 21 | enable = Signal(bool(0)) 22 | reset = Signal(bool(0)) 23 | clk = Signal(bool(0)) 24 | ready = Signal(bool(0)) 25 | 26 | def __init__(self,clk,input_a,output_a,scale=1): 27 | 28 | self.input_a = input_a 29 | 30 | self.output_a = output_a 31 | 32 | self.clk = clk 33 | 34 | self.scale = scale 35 | 36 | self.ready = Signal(bool(False)) 37 | 38 | def processing(self): 39 | enable = self.enable 40 | reset = self.reset 41 | input_a = self.input_a 42 | output_a = self.output_a 43 | clk = self.clk 44 | 45 | output_stall = input_a.output_stall 46 | output_trigger = input_a.output_trigger 47 | output_index = input_a.output_index 48 | 49 | input_stall = output_a.input_stall 50 | input_trigger = output_a.input_trigger 51 | input_index = output_a.input_index 52 | 53 | scale = self.scale 54 | 55 | input_buffer_real = input_a.buffer_real 56 | output_buffer_real = output_a.buffer_real 57 | 58 | ready = self.ready 59 | 60 | #@always(enable.posedge,reset.posedge,input_a.output_stall,output_a.input_stall,clk.posedge) 61 | @always(enable.posedge,clk.posedge) 62 | def initialisation_behaviour(): 63 | if(not ready): ready.next = True 64 | 65 | @always(enable.posedge,reset.posedge,clk.posedge) 66 | def processing_behaviour(): 67 | """print enable 68 | print ready 69 | print output_stall 70 | print input_stall 71 | print output_trigger 72 | print input_trigger""" 73 | 74 | if(enable==True and ready==True and output_stall!=True and input_stall!=True and output_trigger!=True and input_trigger!=True):# and not input_a.output_trigger and not output_a.input_trigger): 75 | #print "%d: Processing - copying %s from input arc, starting at %d to output arc, starting at %d" % (now(),str(input_a.buffer_real[input_a.output_index:input_a.output_index+self.scale]),input_a.output_index,output_a.input_index) 76 | 77 | for i in range(scale): #Assumes that arcs have appropriate number of inputs and outputs set 78 | output_buffer_real[input_index+i].next = input_buffer_real[output_index+i] #Actor just copies data from input to output 79 | #if(output_a.complex_valued and input_a.complex_valued): output_a.buffer_imag[input_index+i].next = input_a.buffer_imag[output_index+i] 80 | 81 | output_trigger.next = True 82 | input_trigger.next = True 83 | 84 | elif(ready): 85 | output_trigger.next = False 86 | input_trigger.next = False 87 | 88 | """@always(clk.negedge) 89 | def processing_behaviour_toggle(): 90 | if(input_a.output_trigger): input_a.output_trigger.next = 0 91 | if(output_a.input_trigger): output_a.input_trigger.next = 0""" 92 | 93 | return processing_behaviour,initialisation_behaviour#,processing_behaviour_toggle 94 | 95 | def logic(self): 96 | processing_inst = self.processing() 97 | 98 | return instances() 99 | 100 | def model(self,input_data): 101 | output_data = input_data 102 | 103 | return output_data 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Toolflow_Code/Arc.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | Arc Base Class 4 | 5 | Created on 22 Dec 2011 6 | @author: Gordon Inggs 7 | ''' 8 | from myhdl import * 9 | 10 | #Code from http://stackoverflow.com/questions/147515/least-common-multiple-for-3-or-more-numbers 11 | def gcd(a, b): 12 | """Return greatest common divisor using Euclid's Algorithm.""" 13 | while b: 14 | a, b = b, a % b 15 | return a 16 | 17 | def lcm(a, b): 18 | """Return lowest common multiple.""" 19 | return a * b // gcd(a, b) 20 | #end of code from http://stackoverflow.com/questions/147515/least-common-multiple-for-3-or-more-numbers 21 | 22 | class Arc: 23 | name = "Arc" 24 | 25 | #input variables and signals 26 | no_inputs = 0 27 | input_index = Signal(intbv(0)) 28 | input_trigger = Signal(bool(False)) #used to indicate that new values have been written 29 | input_bitwidth = 0 30 | input_loop_count = Signal(intbv(0,max=255)) 31 | input_stall = Signal(bool(False)) #full 32 | 33 | #output variables and signals 34 | no_outputs = 0 35 | output_index = Signal(intbv(0)) 36 | output_trigger = Signal(bool(False)) #used to indicate that new values have been read 37 | output_bitwidth = 0 38 | output_loop_count = Signal(intbv(0,max=255)) 39 | output_stall = Signal(bool(True)) #starts off empty 40 | 41 | #class variables 42 | size_factor = 0 43 | size = 0 44 | complex_valued = False 45 | buffer_real = [] 46 | buffer_imag = [] 47 | loop_count_reset = Signal(False) 48 | 49 | reset = Signal(bool(0)) 50 | 51 | def __init__(self,reset,no_inputs,input_bitwidth,no_outputs,output_bitwidth,complex_valued,size_factor): 52 | 53 | #input parameters 54 | self.no_inputs = no_inputs 55 | self.input_bitwidth = input_bitwidth 56 | 57 | #output parameters 58 | self.no_outputs = no_outputs 59 | self.output_bitwidth = output_bitwidth 60 | 61 | #arc parameters 62 | self.complex_valued = complex_valued 63 | self.size_factor = size_factor 64 | self.size = max(lcm(self.no_inputs,self.no_outputs)*self.size_factor,max(self.no_inputs,self.no_outputs)*2) #All buffers have to a minimum of 2 in size, otherwise results in a lot of control logic I don't feel like writing 65 | #Generating the buffer(s) 66 | self.buffer_real = [Signal(intbv(0,min=-2**(self.output_bitwidth-1),max=2**(self.output_bitwidth-1))) for i in range(self.size)] 67 | if(complex_valued): self.buffer_imag = [Signal(intbv(0,min=-2**(self.output_bitwidth-1),max=2**(self.output_bitwidth-1))) for i in range(self.size)] 68 | self.loop_count_reset = Signal(False) 69 | 70 | #input signals 71 | self.input_trigger = Signal(bool(False)) 72 | self.input_stall = Signal(bool(False)) 73 | self.input_index = Signal(intbv(0,min=0,max=self.size)) 74 | self.input_loop_count = Signal(intbv(0,min=0,max=255)) 75 | 76 | self.reset = reset 77 | 78 | #output signals 79 | self.output_trigger = Signal(bool(False)) 80 | self.output_stall = Signal(bool(True)) #Starts empty 81 | self.output_index = Signal(intbv(0,min=0,max=self.size)) 82 | self.output_loop_count = Signal(intbv(0,min=0,max=255)) 83 | 84 | #print id(self.input_trigger) 85 | 86 | def receiving(self): 87 | input_trigger = self.input_trigger 88 | output_trigger = self.output_trigger 89 | input_index = self.input_index 90 | output_index = self.output_index 91 | input_stall = self.input_stall 92 | reset = self.reset 93 | input_loop_count = self.input_loop_count 94 | output_loop_count = self.output_loop_count 95 | no_inputs = self.no_inputs 96 | no_outputs = self.no_outputs 97 | size = self.size 98 | output_stall = self.output_stall 99 | loop_count_reset = self.loop_count_reset 100 | 101 | @always(input_trigger.posedge,reset.posedge,output_trigger.posedge) 102 | def receiving_behaviour(): 103 | if(reset): 104 | input_index.next = 0 105 | input_stall.next = False 106 | input_loop_count.next = 0 107 | 108 | 109 | elif(output_trigger==True and input_stall==True): #data has been read from the Arc, while in a full state 110 | if((((output_index+no_outputs)<=(input_index+no_inputs)) and ((input_index+no_inputs)<=size) and (input_loop_count==output_loop_count)) or (((output_index+no_outputs)>=size) and (input_loop_count==(output_loop_count+1)))): input_stall.next = False #undoing the stall if the new read has freed up enough space 111 | #and (no_outputs<=(input_index+no_inputs)) 112 | elif(input_trigger==True and input_stall!=True): #data samples are being written into the Arc and the Arc is accepting values 113 | if((input_index+no_inputs)=output_index) and (input_loop_count>=output_loop_count))): #checking to see if the next set of samples is within the length of the storage array 114 | 115 | input_index.next = input_index + no_inputs #increment the input pointer 116 | 117 | """print input_index 118 | print output_index 119 | print input_loop_count 120 | print output_loop_count""" 121 | 122 | if((output_index>input_index) and ((input_index+no_inputs)>output_index) and (input_loop_count==output_loop_count)): 123 | #print "input stall" 124 | input_stall.next = True 125 | elif((output_index>input_index) and ((input_index+2*no_inputs)>(output_index+no_outputs)) and (input_loop_count>=output_loop_count)): 126 | #print "input_stall 2" 127 | input_stall.next = True 128 | 129 | 130 | else: #and not(((output_index<=self.no_inputs) and ((input_loop_count+1)==output_loop_count)))): #loop around behaviour 131 | #print "%d: here" % now() 132 | input_index.next = 0 133 | 134 | input_loop_count.next = input_loop_count+1 135 | 136 | """print output_index 137 | print input_loop_count 138 | print output_loop_count""" 139 | 140 | if((output_index<=no_inputs) and ((input_loop_count+1)>=output_loop_count)): 141 | #print "input stalled" 142 | input_stall.next = True# or (((input_loop_count+1)>output_loop_count) and (output_index<=input_index))): 143 | 144 | #checking if the FIFO is full, and hence stalling if so 145 | 146 | #else: input_stall.next = 1 #checking if the FIFO is full, and hence stalling if so 147 | 148 | #if((((output_index+self.no_outputs)<=(input_index+self.no_inputs))) and (output_loop_count<=input_loop_count) or (input_loop_count>output_loop_count)): output_stall.next = 0 #checking to see if there is now sufficient data in the Arc to be read 149 | 150 | return receiving_behaviour#,receiving_stall_behaviour 151 | 152 | def transmitting(self): 153 | input_trigger = self.input_trigger 154 | output_trigger = self.output_trigger 155 | input_index = self.input_index 156 | output_index = self.output_index 157 | input_stall = self.input_stall 158 | reset = self.reset 159 | input_loop_count = self.input_loop_count 160 | output_loop_count = self.output_loop_count 161 | output_stall = self.output_stall 162 | no_inputs = self.no_inputs 163 | no_outputs = self.no_outputs 164 | size = self.size 165 | loop_count_reset = self.loop_count_reset 166 | 167 | 168 | @always(output_trigger.posedge,reset.posedge,input_trigger.posedge) 169 | def transmitting_behaviour(): 170 | 171 | if(reset): 172 | output_index.next = 0 173 | output_stall.next = True 174 | output_loop_count.next = 0 175 | 176 | 177 | elif(input_trigger==True and output_stall==True): #data has been written into the Arc, while in the empty state (output_index+no_outputs)=output_loop_count)) or (((input_index+no_inputs)>=size) and ((input_loop_count+1)>=output_loop_count) and ((output_index+no_outputs)<=no_inputs))): output_stall.next = False #undoing the stall if the new read has freed up enough space 184 | 185 | elif((output_trigger==True) and (output_stall!=True)): #data has been read from the Arc 186 | if((output_index+no_outputs) < size): #if the read is within the current length of the storage array 187 | output_index.next = output_index + no_outputs 188 | 189 | """print "%d: here" % now() 190 | print output_index 191 | print input_index 192 | print output_loop_count 193 | print input_loop_count""" 194 | 195 | if((output_index<=input_index) and ((output_index+no_outputs)>=input_index) and (output_loop_count>=input_loop_count)): output_stall.next = True #checking to see if the array is now empty 196 | elif((output_index<=input_index) and ((output_index+2*no_outputs)>=(input_index+no_inputs)) and (output_loop_count>=input_loop_count)): output_stall.next = True 197 | #print "stalling" 198 | #if((input_index=output_index) and (input_loop_count>=output_loop_count)): 199 | 200 | #elif((input_loop_count==output_loop_count) and (input_index>self.no_inputs) and (output_index>self.no_outputs)): output_loop_count.next = 0 #resetting the loop counter 201 | 202 | else: 203 | output_index.next = 0 #loop around behaviour 204 | output_loop_count.next = output_loop_count + 1 205 | 206 | if((((input_index<=no_outputs)) and (output_loop_count+1)==input_loop_count)): #or ((output_loop_count+1)>input_loop_count)): 207 | output_stall.next = True #checking to see if the array is now empty 208 | 209 | 210 | return transmitting_behaviour#,transmitting_stall_behaviour 211 | 212 | def logic(self): 213 | receive_inst = self.receiving() 214 | transmit_inst = self.transmitting() 215 | 216 | return instances() 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /Toolflow_Code/HDFT/Butterfly.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | Butterfly processing unit, inherits the Actor Base Class 4 | Created on 8 Feb 2012 5 | 6 | @author: Gordon Inggs 7 | ''' 8 | from myhdl import * 9 | import Actor 10 | 11 | class Butterfly(Actor.Actor): 12 | name = "Butterfly" 13 | 14 | output_b = None 15 | 16 | tf_real = () 17 | tf_imag = () 18 | 19 | twiddle_bits = 0 20 | twiddle_factors_real = () 21 | twiddle_factors_imag = () 22 | twiddle_rom_line_real = Signal(intbv(0)) 23 | twiddle_rom_line_imag = Signal(intbv(0)) 24 | twiddle_rom_addr_real = Signal(intbv(0)) 25 | twiddle_rom_addr_imag = Signal(intbv(0)) 26 | 27 | def __init__(self,clk,input_a,output_a,output_b,tf_real,tf_imag,twiddle_bits,scale=1): 28 | Actor.Actor.__init__(self,clk,input_a,output_a,scale) 29 | 30 | self.output_b = output_b 31 | 32 | self.tf_real = tf_real 33 | self.tf_imag = tf_imag 34 | 35 | self.twiddle_bits = twiddle_bits 36 | self.twiddle_factors_real = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs)] 37 | self.twiddle_factors_imag = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs)] 38 | 39 | self.twiddle_rom_line_real = Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) 40 | self.twiddle_rom_line_imag = Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) 41 | 42 | self.twiddle_rom_addr_real = Signal(intbv(0,min=0,max=output_a.no_inputs+1)) 43 | self.twiddle_rom_addr_imag = Signal(intbv(0,min=0,max=output_a.no_inputs+1)) 44 | 45 | self.tf_rom_inst_real = self.rom(self.twiddle_rom_line_real,self.twiddle_rom_addr_real,self.tf_real) 46 | self.tf_rom_inst_imag = self.rom(self.twiddle_rom_line_imag,self.twiddle_rom_addr_imag,self.tf_imag) 47 | 48 | def processing(self): 49 | enable = self.enable 50 | reset = self.reset 51 | input_a = self.input_a 52 | output_a = self.output_a 53 | output_b = self.output_b 54 | tf_real = self.tf_real 55 | tf_imag = self.tf_imag 56 | clk = self.clk 57 | 58 | output_stall = input_a.output_stall 59 | output_trigger = input_a.output_trigger 60 | output_index = input_a.output_index 61 | 62 | input_stall_a = output_a.input_stall 63 | input_trigger_a = output_a.input_trigger 64 | input_index_a = output_a.input_index 65 | 66 | input_stall_b = output_b.input_stall 67 | input_trigger_b = output_b.input_trigger 68 | input_index_b = output_b.input_index 69 | 70 | scale = self.scale 71 | no_inputs = input_a.no_outputs 72 | no_outputs = output_a.no_inputs 73 | 74 | input_buffer_real = input_a.buffer_real 75 | input_buffer_imag = input_a.buffer_imag 76 | output_buffer_a_real = output_a.buffer_real 77 | output_buffer_a_imag = output_a.buffer_imag 78 | output_buffer_b_real = output_b.buffer_real 79 | output_buffer_b_imag = output_b.buffer_imag 80 | 81 | ready = self.ready 82 | 83 | twiddle_rom_addr_real = self.twiddle_rom_addr_real 84 | twiddle_rom_addr_imag = self.twiddle_rom_addr_imag 85 | twiddle_rom_line_real = self.twiddle_rom_line_real 86 | twiddle_rom_line_imag = self.twiddle_rom_line_imag 87 | twiddle_factors_real = self.twiddle_factors_real 88 | twiddle_factors_imag = self.twiddle_factors_imag 89 | 90 | count = Signal(intbv(0,min=0,max=no_outputs+1)) 91 | 92 | @always(enable.posedge,clk.posedge) 93 | def initialisation_behaviour(): 94 | if(enable and clk and (count<(no_outputs))): 95 | ready.next = False 96 | 97 | twiddle_factors_real[count].next = twiddle_rom_line_real 98 | twiddle_factors_imag[count].next = twiddle_rom_line_imag 99 | 100 | if(count<(no_outputs-1)): 101 | twiddle_rom_addr_real.next = count+1 102 | twiddle_rom_addr_imag.next = count+1 103 | 104 | count.next = count+1 105 | 106 | elif(enable and clk): 107 | ready.next = True 108 | 109 | @always(enable.posedge,reset.posedge,clk) 110 | def processing_behaviour(): 111 | if(enable and ready and not output_stall and not input_stall_a and not output_trigger and not input_trigger_a):# and not input_a.output_trigger and not output_a.input_trigger): 112 | for i in range(no_outputs): 113 | output_buffer_a_real[input_index_a+i].next = input_buffer_real[output_index+i] + input_buffer_real[output_index+i+no_inputs/2] 114 | output_buffer_a_imag[input_index_a+i].next = input_buffer_imag[output_index+i] + input_buffer_imag[output_index+i+no_inputs/2] 115 | 116 | input_trigger_a.next = True 117 | elif(enable and ready): 118 | input_trigger_a.next = False 119 | 120 | @always(enable.posedge,reset.posedge,clk) 121 | def processing_behaviour_b(): 122 | if(enable and ready and not output_stall and not input_stall_b and not output_trigger and not input_trigger_b):# and not input_a.output_trigger and not output_a.input_trigger): 123 | #print "%d: Processing - copying %s from input arc, starting at %d to output arc, starting at %d" % (now(),str(input_a.buffer_real[input_a.output_index:input_a.output_index+self.scale]),input_a.output_index,output_a.input_index) 124 | print twiddle_factors_real 125 | for i in range(no_outputs): 126 | output_buffer_b_real[input_index_a+i].next = (input_buffer_real[output_index+i]-input_buffer_real[output_index+i+no_inputs/2])*twiddle_factors_real[i] - (input_buffer_imag[i]-input_buffer_imag[output_index+i+no_inputs/2])*twiddle_factors_imag[i] 127 | output_buffer_b_imag[input_index_a+i].next = (input_buffer_real[output_index+i]-input_buffer_real[output_index+i+no_inputs/2])*twiddle_factors_imag[i] + (input_buffer_imag[i]-input_buffer_imag[output_index+i+no_inputs/2])*twiddle_factors_real[i] 128 | 129 | output_trigger.next = True 130 | input_trigger_b.next = True 131 | elif(enable and ready): 132 | output_trigger.next = False 133 | input_trigger_b.next = False 134 | 135 | return processing_behaviour, processing_behaviour_b, initialisation_behaviour 136 | 137 | def model(self,input_data): 138 | output_data = [[],[]] 139 | 140 | for i in range(self.output_a.no_inputs): 141 | output_data[0].append(input_data[i]+input_data[i+self.output_a.no_inputs]) 142 | output_data[1].append((input_data[i]-input_data[i+self.output_a.no_inputs])*(self.tf_real[i]+1.0j*self.tf_imag[i])) 143 | 144 | return output_data 145 | 146 | def rom(self,dout, addr, CONTENT): 147 | """ 148 | DivideAndConquer rom behaviour 149 | this independent module is used to provide the ROM for the twiddle factors that are required 150 | """ 151 | @always_comb 152 | def read(): 153 | dout.next = CONTENT[int(addr)] 154 | 155 | return read 156 | 157 | def logic(self): 158 | processing_inst = self.processing() 159 | 160 | tf_rom_inst_real = self.tf_rom_inst_real 161 | tf_rom_inst_imag = self.tf_rom_inst_imag 162 | 163 | return instances() 164 | 165 | -------------------------------------------------------------------------------- /Toolflow_Code/HDFT/DFT.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | DFT unit, inherits the Actor Base Class 4 | Created on 13 Feb 2012 5 | 6 | @author: Gordon Inggs 7 | ''' 8 | from myhdl import * 9 | import Actor 10 | 11 | class DFT(Actor.Actor): 12 | name = "DFT" 13 | 14 | tf_real = () 15 | tf_imag = () 16 | 17 | twiddle_bits = 0 18 | twiddle_factors_real = [] 19 | twiddle_factors_imag = [] 20 | 21 | twiddle_bits = 0 22 | twiddle_factors_real = (()) 23 | twiddle_factors_imag = (()) 24 | twiddle_rom_line_real = [] 25 | twiddle_rom_line_imag = [] 26 | twiddle_rom_addr_real = [] 27 | twiddle_rom_addr_imag = [] 28 | 29 | def __init__(self,clk,input_a,output_a,tf_real,tf_imag,twiddle_bits,scale=1): 30 | Actor.Actor.__init__(self,clk,input_a,output_a,scale) 31 | 32 | self.twiddle_bits = twiddle_bits 33 | self.twiddle_factors_real = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs*self.output_a.no_inputs)] 34 | self.twiddle_factors_imag = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs*self.output_a.no_inputs)] 35 | 36 | self.twiddle_rom_line_real = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs)] 37 | self.twiddle_rom_line_imag = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(self.output_a.no_inputs)] 38 | 39 | self.twiddle_rom_addr_real = Signal(intbv(0,min=0,max=output_a.no_inputs+1)) 40 | self.twiddle_rom_addr_imag = Signal(intbv(0,min=0,max=output_a.no_inputs+1)) 41 | 42 | self.tf_real = tf_real 43 | self.tf_imag = tf_imag 44 | 45 | self.tf_rom_inst_real = [self.rom(self.twiddle_rom_line_real[i],self.twiddle_rom_addr_real,self.tf_real[i]) for i in range(output_a.no_inputs)] 46 | self.tf_rom_inst_imag = [self.rom(self.twiddle_rom_line_imag[i],self.twiddle_rom_addr_imag,self.tf_imag[i]) for i in range(output_a.no_inputs)] 47 | 48 | def processing(self): 49 | enable = self.enable 50 | reset = self.reset 51 | input_a = self.input_a 52 | output_a = self.output_a 53 | clk = self.clk 54 | 55 | output_stall = input_a.output_stall 56 | output_trigger = input_a.output_trigger 57 | output_index = input_a.output_index 58 | 59 | input_stall_a = output_a.input_stall 60 | input_trigger_a = output_a.input_trigger 61 | input_index_a = output_a.input_index 62 | 63 | scale = self.scale 64 | no_inputs = input_a.no_outputs 65 | no_outputs = output_a.no_inputs 66 | output_bitwidth = output_a.input_bitwidth 67 | 68 | input_buffer_real = input_a.buffer_real 69 | input_buffer_imag = input_a.buffer_imag 70 | 71 | output_buffer_real = output_a.buffer_real 72 | output_buffer_imag = output_a.buffer_imag 73 | 74 | ready = self.ready 75 | 76 | twiddle_rom_addr_real = self.twiddle_rom_addr_real 77 | twiddle_rom_addr_imag = self.twiddle_rom_addr_imag 78 | twiddle_rom_line_real = self.twiddle_rom_line_real 79 | twiddle_rom_line_imag = self.twiddle_rom_line_imag 80 | twiddle_factors_real = self.twiddle_factors_real 81 | twiddle_factors_imag = self.twiddle_factors_imag 82 | 83 | count = Signal(intbv(0,min=0,max=no_inputs+1)) 84 | 85 | @always(enable.posedge,clk.posedge) 86 | def initialisation_behaviour(): 87 | if(enable and clk and (count<(no_inputs))): 88 | ready.next = False 89 | 90 | for i in range(no_inputs): 91 | twiddle_factors_real[no_inputs*count+i].next = twiddle_rom_line_real[i] 92 | twiddle_factors_imag[no_inputs*count+i].next = twiddle_rom_line_imag[i] 93 | 94 | if(count<(no_outputs-1)): 95 | twiddle_rom_addr_real.next = count+1 96 | twiddle_rom_addr_imag.next = count+1 97 | 98 | count.next = count + 1 99 | 100 | elif(enable and clk): 101 | ready.next = True 102 | 103 | @always(enable.posedge,reset.posedge,clk) 104 | def processing_behaviour(): 105 | if(enable and ready and not output_stall and not input_stall_a and not output_trigger and not input_trigger_a):# and not input_a.output_trigger and not output_a.input_trigger): 106 | for i in range(no_inputs): 107 | temp_value_real = intbv(0,min=-2**(output_bitwidth-1),max=2**(output_bitwidth-1)) 108 | temp_value_imag = intbv(0,min=-2**(output_bitwidth-1),max=2**(output_bitwidth-1)) 109 | for j in range(no_inputs): 110 | temp_value_real += input_buffer_real[output_index+j]*(twiddle_factors_real[j*no_inputs+i]+twiddle_factors_imag[j*no_inputs+i]) - twiddle_factors_imag[j*no_inputs+i]*(input_buffer_real[output_index+j]+input_buffer_imag[output_index+j]) 111 | temp_value_imag += input_buffer_real[output_index+j]*(twiddle_factors_real[j*no_inputs+i]+twiddle_factors_imag[j*no_inputs+i]) + twiddle_factors_real[j*no_inputs+i]*(input_buffer_imag[output_index+j]-input_buffer_real[output_index+j]) 112 | 113 | output_buffer_real[input_index_a+i].next = temp_value_real 114 | output_buffer_imag[input_index_a+i].next = temp_value_imag 115 | 116 | input_trigger_a.next = True 117 | elif(enable and ready): 118 | input_trigger_a.next = False 119 | 120 | return processing_behaviour,initialisation_behaviour 121 | 122 | def model(self,input_data): 123 | output_data = [] 124 | 125 | for i in range(len(input_data)): 126 | temp_value = 0.0 127 | count = 0 128 | for i_d in input_data: 129 | temp_value += (i_d)*(self.tf_real[i][count]+1j*self.tf_imag[i][count]) 130 | count += 1 131 | 132 | output_data.append(temp_value) 133 | 134 | return output_data 135 | 136 | def rom(self,dout, addr, CONTENT): 137 | """ 138 | DFT rom behaviour 139 | this independent module is used to provide the ROM for the twiddle factors that are required 140 | """ 141 | @always_comb 142 | def read(): 143 | dout.next = CONTENT[int(addr)] 144 | 145 | return read 146 | 147 | def logic(self): 148 | processing_inst = self.processing() 149 | 150 | tf_rom_inst_real = self.tf_rom_inst_real 151 | tf_rom_inst_imag = self.tf_rom_inst_imag 152 | 153 | return instances() -------------------------------------------------------------------------------- /Toolflow_Code/HDFT/Pipeline_Mux.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | Pipeline Mux unit, inherits the Actor Base Class 4 | Created on 9 Feb 2012 5 | 6 | @author: Gordon Inggs 7 | ''' 8 | from myhdl import * 9 | import Actor 10 | 11 | class Pipeline_Mux(Actor.Actor): 12 | name = "Pipeline_Mux" 13 | 14 | input_a = [] 15 | 16 | input_line_no = Signal(intbv(0)) 17 | 18 | def __init__(self, clk, input_a, output_a, scale=1): 19 | Actor.Actor.__init__(self, clk, input_a, output_a, scale) 20 | 21 | self.input_line_no = Signal(intbv(0,min=0,max=len(input_a))) 22 | 23 | def processing(self): 24 | enable = self.enable 25 | reset = self.reset 26 | input_a = self.input_a 27 | output_a = self.output_a 28 | clk = self.clk 29 | input_line_no = self.input_line_no 30 | 31 | output_stall = [i_a.output_stall for i_a in self.input_a] 32 | output_trigger = [i_a.output_trigger for i_a in self.input_a] 33 | output_index = [i_a.output_index for i_a in self.input_a] 34 | 35 | input_stall = output_a.input_stall 36 | input_trigger = output_a.input_trigger 37 | input_index = output_a.input_index 38 | 39 | scale = self.scale 40 | 41 | input_buffer_real = [] 42 | for i_a in self.input_a: 43 | input_buffer_real.extend(i_a.buffer_real) 44 | 45 | no_inputs = len(self.input_a[0].buffer_real) 46 | 47 | output_buffer_real = output_a.buffer_real 48 | 49 | ready = self.ready 50 | 51 | #@always(enable.posedge,reset.posedge,input_a.output_stall,output_a.input_stall,clk.posedge) 52 | @always(enable.posedge,clk.posedge) 53 | def initialisation_behaviour(): 54 | if(not ready): ready.next = True 55 | 56 | @always(enable.posedge,reset.posedge,clk) 57 | def processing_behaviour(): 58 | if(enable and ready and not output_stall[input_line_no] and not input_stall and not output_trigger[input_line_no] and not input_trigger):# and not input_a.output_trigger and not output_a.input_trigger): 59 | #print "%d: Processing - copying %s from input arc, starting at %d to output arc, starting at %d" % (now(),str(input_a.buffer_real[input_a.output_index:input_a.output_index+self.scale]),input_a.output_index,output_a.input_index) 60 | 61 | for i in range(scale): #Assumes that arcs have appropriate number of inputs and outputs set 62 | output_buffer_real[input_index+i].next = input_buffer_real[input_line_no*no_inputs+output_index[input_line_no]+i] #Actor just copies data from input to output 63 | #if(output_a.complex_valued and input_a.complex_valued): output_a.buffer_imag[input_index+i].next = input_a.buffer_imag[output_index+i] 64 | 65 | output_trigger[input_line_no].next = True 66 | input_trigger.next = True 67 | 68 | elif(ready): 69 | output_trigger[input_line_no].next = False 70 | input_trigger.next = False 71 | 72 | if(input_line_no<(len(input_a)-1) and output_trigger[input_line_no] and input_trigger): input_line_no.next = input_line_no+1 73 | elif(output_trigger[input_line_no] and input_trigger): input_line_no.next = 0 74 | 75 | """@always(clk.negedge) 76 | def processing_behaviour_toggle(): 77 | if(input_a.output_trigger): input_a.output_trigger.next = 0 78 | if(output_a.input_trigger): output_a.input_trigger.next = 0""" 79 | 80 | return processing_behaviour,initialisation_behaviour#,processing_behaviour_toggle 81 | 82 | def model(self,input_a): 83 | output_dataset = [] 84 | for i in input_a: 85 | output_dataset.extend(i) -------------------------------------------------------------------------------- /Toolflow_Code/HDFT/Reorderer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MyHDL-based FPGA DSP Toolflow 3 | Reorderer unit, inherits the Actor Base Class 4 | Created on 13 Feb 2012 5 | 6 | @author: Gordon Inggs 7 | ''' 8 | from myhdl import * 9 | import Actor 10 | 11 | class Reorderer(Actor.Actor): 12 | name = "Reorderer" 13 | 14 | indices = () 15 | index_array = [] 16 | 17 | index_rom_line = Signal(intbv(0)) 18 | index_rom_addr = Signal(intbv(0)) 19 | 20 | index_rom = None 21 | 22 | def __init__(self,clk,input_a,output_a,indices,scale=1): 23 | Actor.Actor.__init__(self,clk,input_a,output_a,scale) 24 | 25 | self.indices = indices 26 | 27 | self.index_rom_line = Signal(intbv(0,min=0,max=len(indices))) 28 | self.index_rom_addr = Signal(intbv(0,min=0,max=len(indices))) 29 | 30 | self.index_rom = self.rom(self.index_rom_line,self.index_rom_addr,self.indices) 31 | self.index_array = [Signal(intbv(0,min=0,max=self.scale)) for i in range(self.scale)] 32 | 33 | def processing(self): 34 | enable = self.enable 35 | reset = self.reset 36 | input_a = self.input_a 37 | output_a = self.output_a 38 | clk = self.clk 39 | 40 | output_stall = input_a.output_stall 41 | output_trigger = input_a.output_trigger 42 | output_index = input_a.output_index 43 | 44 | input_stall = output_a.input_stall 45 | input_trigger = output_a.input_trigger 46 | input_index = output_a.input_index 47 | 48 | scale = self.scale 49 | no_inputs = input_a.no_outputs 50 | no_outputs = output_a.no_inputs 51 | 52 | input_buffer_real = input_a.buffer_real 53 | output_buffer_real = output_a.buffer_real 54 | 55 | ready = self.ready 56 | 57 | index_array = self.index_array 58 | index_rom_line = self.index_rom_line 59 | index_rom_addr = self.index_rom_addr 60 | 61 | count = Signal(intbv(0,min=0,max=scale+1)) 62 | 63 | #@always(enable.posedge,reset.posedge,input_a.output_stall,output_a.input_stall,clk.posedge) 64 | @always(enable.posedge,clk.posedge) 65 | def initialisation_behaviour(): 66 | if(enable and clk and (count clock signal, used to synchronise behaviour across the module 56 | reset -> asynchronous reset line, used to restart the behaviour of the module 57 | 58 | *Data Signals* 59 | **Input** 60 | input_line_real -> input data line for the real part of the input signal 61 | input_line_imag -> input data line for the imaginary part of the input signal 62 | input_trigger -> input signal (1 bit) line used to indicate that data may be read into the actor 63 | input_enable -> actually an output signal line used to indicate that the actor is ready to read new data 64 | 65 | **Output** 66 | output_line_real -> output data line for the real part of the output signal 67 | output_line_imag -> output data line for the imaginary part of the output signal 68 | output_trigger -> output signal (1 bit) line used to indicate that data is ready to be read from the actor 69 | output_enable -> actually an input signal line used to indicate to the module that the following actor is ready to read from it 70 | 71 | *Normal Parameters* 72 | no_inputs -> integer value specifying how many samples need to be read into the actor before it processes that data 73 | no_outputs -> integer value specifying how many samples will be produced upon the completion of its processing activity 74 | input_bitsize -> the size of each of the input data lines 75 | output_bitsize -> the size of each of the output data line 76 | 77 | """ 78 | self.no_inputs = no_inputs 79 | if(self.no_inputs): self.input_count = Signal(intbv(0,min=0,max=self.no_inputs+1)) 80 | self.input_bitsize = input_bitsize 81 | 82 | self.input_line_real = input_line_real 83 | self.input_line_imag = input_line_imag 84 | self.input_trigger = input_trigger 85 | self.input_enable = input_enable 86 | 87 | if(self.input_bitsize): #creating input buffers 88 | self.input_buffer_real = [Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1))) for i in range(no_inputs)] 89 | self.input_buffer_imag = [Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1))) for i in range(no_inputs)] 90 | else: 91 | self.input_buffer_real = [Signal(intbv(0)) for i in range(no_inputs)] 92 | self.input_buffer_imag = [Signal(intbv(0)) for i in range(no_inputs)] 93 | 94 | self.no_outputs = no_outputs 95 | if(self.no_outputs): self.output_count = Signal(intbv(0,min=0,max=self.no_outputs+1)) #internal count variable 96 | self.output_bitsize = output_bitsize 97 | 98 | self.output_line_real = output_line_real 99 | self.output_line_imag = output_line_imag 100 | self.output_trigger = output_trigger 101 | self.output_enable = output_enable 102 | 103 | if(self.output_bitsize): #creating output buffer 104 | self.output_buffer_real = [Signal(intbv(0,min=-2**(self.output_bitsize-1),max=2**(self.output_bitsize-1))) for i in range(no_outputs)] 105 | self.output_buffer_imag = [Signal(intbv(0,min=-2**(self.output_bitsize-1),max=2**(self.output_bitsize-1))) for i in range(no_outputs)] 106 | else: 107 | self.output_buffer_real = [Signal(intbv(0)) for i in range(no_outputs)] 108 | self.output_buffer_imag = [Signal(intbv(0)) for i in range(no_outputs)] 109 | 110 | self.reset = reset 111 | self.clk = clk 112 | 113 | self.verbosity = verbosity 114 | 115 | self.processing_input_enable = Signal(bool(1)) #creating internal control signals 116 | self.processing_input_trigger = Signal(bool(0)) 117 | self.processing_output_enable = Signal(bool(1)) 118 | self.processing_output_trigger = Signal(bool(0)) 119 | 120 | self.receiving_flag = Signal(bool(0)) 121 | self.transmitting_flag = Signal(bool(0)) 122 | self.processing_flag = Signal(bool(0)) 123 | self.receive_stall_flag = Signal(bool(0)) 124 | 125 | if((self.input_bitsize-self.output_bitsize)>0): #calculating if there is any truncation i.e. input bitsize > output bitsize 126 | self.bit_shift = (self.input_bitsize-self.output_bitsize) 127 | 128 | def receiving(self): 129 | """ 130 | Actor receiving behaviour 131 | primarily works with the actor input and control signals 132 | """ 133 | input_line_real = self.input_line_real #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 134 | input_line_imag = self.input_line_imag 135 | input_trigger = self.input_trigger 136 | input_enable = self.input_enable 137 | reset = self.reset 138 | clk = self.clk 139 | 140 | input_count = self.input_count 141 | no_inputs = self.no_inputs 142 | input_buffer_real = self.input_buffer_real 143 | input_buffer_imag = self.input_buffer_imag 144 | 145 | processing_input_enable = self.processing_input_enable 146 | processing_input_trigger = self.processing_input_trigger 147 | 148 | receiving_flag = self.receiving_flag 149 | receive_stall_flag = self.receive_stall_flag 150 | 151 | @always(clk.posedge,reset.posedge) 152 | def receiving_logic(): 153 | if(reset==1): #asynchronous reset 154 | input_count.next = 0 155 | input_enable.next = 0 156 | processing_input_trigger.next = 0 157 | receiving_flag.next = 0 158 | receive_stall_flag.next = 0 159 | 160 | elif((receiving_flag==1)): 161 | if(input_count<(no_inputs)): #Populating the input buffer 162 | input_buffer_real[int(input_count)].next = input_line_real 163 | input_buffer_imag[int(input_count)].next = input_line_imag 164 | 165 | input_count.next = input_count + 1 166 | 167 | else: #When the input buffer is full, copy the last value, trigger the processing and stall the input 168 | input_count.next = 0 169 | input_enable.next = 0 170 | processing_input_trigger.next = 1 171 | receiving_flag.next = 0 172 | receive_stall_flag.next = 1 173 | 174 | else: 175 | if((receive_stall_flag==1)): #stall for a clock cycle 176 | receive_stall_flag.next = 0 177 | 178 | elif((input_trigger==1) and (processing_input_enable==1)): #if there is data waiting to be read and there is no internal processing going on, start the receive behaviour 179 | receiving_flag.next = 1 180 | input_enable.next = 0 #indicate no new inputs 181 | processing_input_trigger.next = 0 #indicate that processing can not occur (while data is being read) 182 | 183 | elif((processing_input_enable==1)): # if there is no data waiting to be read and the internal processing is done, indicate that internal processing may start 184 | input_enable.next = 1 185 | processing_input_trigger.next = 0 186 | 187 | return receiving_logic 188 | 189 | def transmiting(self): 190 | """ 191 | Actor transmitting behaviour 192 | primarily works with the actor output and control signals 193 | """ 194 | processing_output_trigger = self.processing_output_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 195 | output_enable = self.output_enable 196 | output_count = self.output_count 197 | no_outputs = self.no_outputs 198 | output_line_real = self.output_line_real 199 | output_line_imag = self.output_line_imag 200 | output_buffer_real = self.output_buffer_real 201 | output_buffer_imag = self.output_buffer_imag 202 | processing_output_enable = self.processing_output_enable 203 | output_trigger = self.output_trigger 204 | reset = self.reset 205 | transmitting_flag = self.transmitting_flag 206 | clk = self.clk 207 | stall_flag = Signal(bool(0)) 208 | pending_flag = Signal(bool(0)) 209 | 210 | @always(clk.posedge,reset.posedge) 211 | def transmiting_logic(): 212 | if(reset==1): #asynchronous reset 213 | output_count.next = 0 214 | output_line_real.next = 0 215 | output_line_imag.next = 0 216 | processing_output_enable.next = 1 217 | output_trigger.next = 0 218 | transmitting_flag.next = 0 219 | stall_flag.next = 1 220 | pending_flag.next = 0 221 | 222 | elif((transmitting_flag==1)): 223 | if(output_count<(no_outputs)): 224 | output_line_real.next = output_buffer_real[int(output_count)] #Outputing values 225 | output_line_imag.next = output_buffer_imag[int(output_count)] 226 | processing_output_enable.next = 0 227 | output_count.next = output_count + 1 228 | 229 | else: #When the output buffer has been fully transmitted... 230 | output_trigger.next = 0 #indicate that there are no new values available 231 | output_count.next = 0 232 | transmitting_flag.next = 0 233 | processing_output_enable.next = 1 #indicate that processing may run again 234 | stall_flag.next = 1 235 | 236 | else: 237 | if(stall_flag==1): stall_flag.next = 0 #stall for a clock cycle 238 | 239 | elif((output_enable==1) and (processing_output_trigger==1)): #if output is allowed and processing is complete, start the transmitting behaviour 240 | transmitting_flag.next = 1 241 | output_trigger.next = 1 242 | processing_output_enable.next = 0 243 | pending_flag.next = 0 244 | 245 | elif((output_enable==1) and (pending_flag!=1)): #if output is allowed and there is no output data pending, indicate that processing can occur 246 | processing_output_enable.next = 1 247 | 248 | elif((processing_output_trigger==1)): #if processing is complete, but output is not allowed, raise the pending flag and stall any future processing 249 | pending_flag.next = 1 250 | processing_output_enable.next = 0 251 | 252 | return transmiting_logic 253 | 254 | def processing(self): 255 | """ 256 | Actor processing behaviour 257 | primarily works with the two buffers and the internal signals 258 | """ 259 | processing_input_trigger = self.processing_input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 260 | processing_output_enable = self.processing_output_enable 261 | output_buffer_real = self.output_buffer_real 262 | output_buffer_imag = self.output_buffer_imag 263 | input_buffer_real = self.input_buffer_real 264 | input_buffer_imag = self.input_buffer_imag 265 | processing_output_trigger = self.processing_output_trigger 266 | input_enable = self.input_enable 267 | processing_input_enable = self.processing_input_enable 268 | no_inputs = self.no_inputs 269 | no_outputs = self.no_outputs 270 | reset = self.reset 271 | clk = self.clk 272 | processing_flag = self.processing_flag 273 | busy = Signal(bool(0)) 274 | stall_flag = Signal(bool(0)) 275 | bit_shift = self.bit_shift 276 | 277 | @always(reset.posedge,clk.posedge) 278 | def processing_logic(): 279 | if(reset==1): #asynchronous reset 280 | processing_output_trigger.next = 0 281 | processing_input_enable.next = 1 282 | processing_flag.next = 0 283 | busy.next = 1 284 | stall_flag.next = 0 285 | 286 | elif(processing_flag==1): #Only process if the trigger and enable line are high 287 | if(busy==1): 288 | for i in range(no_inputs): #trivial behaviour - copies values from input buffer to output buffer 289 | output_buffer_real[i].next = (int(input_buffer_real[i]) >> bit_shift) 290 | output_buffer_imag[i].next = (int(input_buffer_imag[i]) >> bit_shift) 291 | busy.next = 0 292 | 293 | else: #when complete set all of the control signals correctly 294 | processing_output_trigger.next = 1 295 | processing_input_enable.next = 1 296 | processing_flag.next = 0 297 | busy.next = 1 298 | stall_flag.next = 1 299 | 300 | else: 301 | if(stall_flag==1): stall_flag.next = 0 #stall for a clock cycle 302 | 303 | elif((processing_input_trigger==1) and (processing_output_enable==1)): #if the input trigger is set and the output is allowed, start processing 304 | processing_flag.next = 1 305 | busy.next = 1 306 | processing_input_enable.next = 0 307 | processing_output_trigger.next = 0 308 | 309 | elif(processing_output_enable==1): #if only output is allowed, indicate that there is no new data 310 | processing_output_trigger.next = 0 311 | 312 | elif(processing_input_trigger==1): #if the input trigger is set, indicate to stall the input data 313 | processing_input_enable.next = 0 314 | 315 | return processing_logic 316 | 317 | def logic(self): 318 | """ 319 | Actor logic method 320 | calls all of the behavioural methods, for conversion purposes 321 | """ 322 | receive_inst = self.receiving() 323 | transmit_inst = self.transmiting() 324 | process_inst = self.processing() 325 | 326 | return instances() 327 | 328 | def model(self,input_values_real,input_values_imag): 329 | """ 330 | Actor model method 331 | performs the same operation as the processing method of the actor, but does it upon a Python list 332 | 333 | Parameters: 334 | input_values_real -> input list of the real values 335 | input_values_imag -> input list of the imaginary values 336 | 337 | Output: 338 | [output real values list, output imaginary values list] 339 | """ 340 | output_values_real = [] 341 | output_values_imag = [] 342 | 343 | for i_v in input_values_real: 344 | temp = [] 345 | for i in i_v: 346 | temp.append(i >> self.bit_shift) 347 | 348 | output_values_real.append(temp) 349 | 350 | for i_v in input_values_imag: 351 | temp = [] 352 | for i in i_v: 353 | temp.append(i >> self.bit_shift) 354 | 355 | output_values_imag.append(temp) 356 | 357 | return [output_values_real,output_values_imag] -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/DFT.py: -------------------------------------------------------------------------------- 1 | #DFT class 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import Actor,math,numpy 7 | 8 | class DFT(Actor.Actor): 9 | name = "DFT" 10 | 11 | multiplier_bitsize = 0 #parameters 12 | twiddle_factor_bitsize = 0 13 | 14 | iteration_count = Signal(intbv(0)) 15 | iteration_start = Signal(bool(0)) 16 | iteration_finished = Signal(bool(0)) 17 | processing_iteration = Signal(bool(0))#,delay=1) 18 | clear_output = Signal(bool(0)) 19 | pull_up = Signal(bool(1)) 20 | #processing_iteration_done = Signal(bool(0)) 21 | 22 | twiddle_factor_units = [] #twiddle roms used to store twiddle values 23 | twiddle_factor_units_output_real = [] #output signals from twiddle roms 24 | twiddle_factor_units_output_imag = [] 25 | 26 | multipliers = [] #normal multiplers used in the complex multiplication task 27 | multiplier_signals = [] #signals used to communicate within the complex multipliers 28 | 29 | complex_multiplier_loaders = [] #units that do the pre-multiplication addition for the complex multiplication operation 30 | complex_multiplier_adders = [] #units that do the post-multiplcation addition for the complex multiplication operation 31 | multipliers_output_real = [] #output signals from the complex multipliers 32 | multipliers_output_imag = [] 33 | 34 | complex_adders = [] #complex adder units used to sum outputs input value multiplication with twiddle factors 35 | complex_adders_output_real = [] #output signals from the adders 36 | complex_adders_output_imag = [] 37 | complex_adders_output_trigger = [] #output triggers for adder units, used to trigger the next adder in the set, and reset the previous set 38 | 39 | tf_real= (()) #list of tuples of twiddle factor values 40 | tf_imag = (()) 41 | 42 | def __init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,reset,clk,tf_real,tf_imag,input_bitsize=0,output_bitsize=0,multiplier_bitsize=0,twiddle_factor_bitsize=0,verbosity=False): 43 | """ 44 | DFT Constructor 45 | Parameters: 46 | *Control Signals* 47 | clk -> clock signal, used to synchronise behaviour across the module 48 | reset -> asynchronous reset line, used to restart the behaviour of the module 49 | 50 | *Data Signals* 51 | **Input** 52 | input_line_real -> input data line for the real part of the input signal 53 | input_line_imag -> input data line for the imaginary part of the input signal 54 | input_trigger -> input signal (1 bit) line used to indicate that data may be read into the actor 55 | input_enable -> actually an output signal line used to indicate that the actor is ready to read new data 56 | 57 | **Output** 58 | output_line_real -> output data line for the real part of the output signal 59 | output_line_imag -> output data line for the imaginary part of the output signal 60 | output_trigger -> output signal (1 bit) line used to indicate that data is ready to be read from the actor 61 | output_enable -> actually an input signal line used to indicate to the module that the following actor is ready to read from it 62 | 63 | *Normal Parameters* 64 | no_inputs -> integer value specifying how many samples need to be read into the actor before it processes that data 65 | no_outputs -> integer value specifying how many samples will be produced upon the completion of its processing activity 66 | input_bitsize -> the bit size of each of the input data lines 67 | output_bitsize -> the bit size of each of the output data line 68 | multiplier_bitsize -> the bit size of the result of the DFT operation 69 | twiddle_factor_bitsize -> the bit size of the twiddle factors used in the DFT 70 | tf_real -> list containing real parts of the twiddle factors used in the DFT 71 | tf_imag -> list containing imaginary parts of the twiddle factors used in the DFT 72 | 73 | """ 74 | Actor.Actor.__init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,reset,clk,input_bitsize,output_bitsize) #Call to base class constructor 75 | 76 | self.multiplier_bitsize = multiplier_bitsize 77 | self.twiddle_factor_bitsize = twiddle_factor_bitsize 78 | 79 | if(self.no_inputs): 80 | self.iteration_count = Signal(intbv(0,min=0,max=self.no_inputs+1)) 81 | self.processing_count = Signal(intbv(0,min=0,max=self.no_inputs+1)) 82 | 83 | self.tf_real = tf_real 84 | self.tf_imag = tf_imag 85 | 86 | 87 | def processing(self): #overiding processing logic 88 | """ 89 | DFT processing behaviour 90 | primarily works with the two buffers and the internal signals 91 | """ 92 | processing_input_trigger = self.processing_input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 93 | processing_output_enable = self.processing_output_enable 94 | output_buffer_real = self.output_buffer_real 95 | output_buffer_imag = self.output_buffer_imag 96 | input_buffer_real = self.input_buffer_real 97 | input_buffer_imag = self.input_buffer_imag 98 | processing_output_trigger = self.processing_output_trigger 99 | input_enable = self.input_enable 100 | processing_input_enable = self.processing_input_enable 101 | no_inputs = self.no_inputs 102 | no_outputs = self.no_outputs 103 | reset = self.reset 104 | clk = self.clk 105 | processing_flag = self.processing_flag 106 | busy = Signal(bool(0)) 107 | stall_flag = Signal(bool(0)) 108 | 109 | iteration_count = self.iteration_count 110 | processing_iteration = self.processing_iteration 111 | iteration_finished = self.iteration_finished 112 | iteration_start = self.iteration_start 113 | loop_count = Signal(intbv(0,min=0,max=self.no_inputs+1)) 114 | processing_flag = Signal(bool(0)) 115 | pull_up = self.pull_up 116 | 117 | complex_adders_output_trigger = self.complex_adders_output_trigger 118 | complex_adders_output_real = self.complex_adders_output_real 119 | complex_adders_output_imag = self.complex_adders_output_imag 120 | 121 | @always(clk.posedge,reset.posedge) 122 | def processing_logic(): 123 | if(reset): #asynchronous reset 124 | processing_output_trigger.next = 0 125 | processing_input_enable.next = 1 126 | processing_flag.next = 0 127 | busy.next = 1 128 | stall_flag.next = 0 129 | pull_up.next = 1 130 | 131 | elif(processing_flag): 132 | if(busy and (loop_count<2)): 133 | loop_count.next = loop_count + 1 134 | processing_iteration.next = not(processing_iteration) #trigger the adders 135 | 136 | elif(busy): 137 | loop_count.next = 0 138 | output_buffer_real[iteration_count].next = complex_adders_output_real[-1] #copy the output from the last iteration into the output buffer 139 | output_buffer_imag[iteration_count].next = complex_adders_output_imag[-1] 140 | 141 | if(iteration_count<(no_inputs-1)): 142 | iteration_count.next = iteration_count + 1 #increment the iterator 143 | 144 | else: 145 | busy.next = 0 146 | 147 | else: 148 | iteration_count.next = 0 149 | 150 | processing_output_trigger.next = 1 #indicate that processing is done 151 | processing_input_enable.next = 1 152 | processing_flag.next = 0 153 | busy.next = 1 154 | loop_count.next = 0 155 | stall_flag.next = 1 156 | 157 | 158 | else: 159 | if(stall_flag): stall_flag.next = 0 #stall for one clock cycle 160 | 161 | elif((processing_output_enable) and processing_input_trigger): #Only process if the trigger and enable line are high 162 | processing_flag.next = 1 163 | pull_up.next = 1 164 | busy.next = 1 165 | processing_input_enable.next = 0 166 | processing_output_trigger.next = 0 167 | 168 | elif(processing_output_enable): 169 | processing_output_trigger.next = 0 170 | 171 | return instances() 172 | 173 | def rom(self,dout, addr, CONTENT): 174 | """ 175 | DFT rom method 176 | used to create memory used to store Twiddle Factors 177 | """ 178 | @always_comb 179 | def read(): 180 | dout.next = CONTENT[int(addr)] 181 | 182 | return read 183 | 184 | def multi(self,output,input_a,input_b,clk,reset,name,pull_up): 185 | """ 186 | DFT multiplier method 187 | used to a multiplier 188 | """ 189 | 190 | @always(clk.posedge) 191 | def multi_logic(): 192 | output.next = input_a*input_b 193 | 194 | #Old depreciated method of overiding conversion 195 | __verilog__ =\ 196 | """ 197 | MULT18X18SIO #( .AREG(1), .BREG(1), .PREG(1), .B_INPUT(\"DIRECT\") ) %(name)s (.A(%(input_a)s),.B(%(input_b)s),.BCIN(),.CEA(%(pull_up)s),.CEB(%(pull_up)s),.CEP(%(pull_up)s),.CLK(%(clk)s),.RSTA(%(reset)s),.RSTB(%(reset)s),.RSTP(%(reset)s),.BCOUT(),.P(%(output)s)); 198 | """ 199 | 200 | return multi_logic 201 | 202 | #overiding verilog conversion varible so as to use hardware multiplier 203 | multi.verilog_code =\ 204 | """ 205 | MULT18X18SIO #( .AREG(1), .BREG(1), .PREG(1), .B_INPUT(\"DIRECT\") ) $name (.A($input_a),.B($input_b),.BCIN(),.CEA($self.pull_up),.CEB($self.pull_up),.CEP($self.pull_up),.CLK($clk),.RSTA($reset),.RSTB($reset),.RSTP($resett),.BCOUT(),.P($output)); 206 | """ 207 | #MULT18X18SIO #( .AREG(1), .BREG(1), .PREG(1), .B_INPUT("DIRECT") ) XLXI_37 (.A(XLXN_142[17:0]),.B(XLXN_141[17:0]),.BCIN(),.CEA(XLXN_148),.CEB(XLXN_148),.CEP(XLXN_148),.CLK(XLXN_140),.RSTA(reset),.RSTB(reset),.RSTP(reset),.BCOUT(),.P(XLXN_128[35:0])); 208 | 209 | 210 | def complex_multiplier_loader(self,input_a_real,input_a_imag,input_b_real,input_b_imag,multiplier_1_input_a_signal,multiplier_1_input_b_signal,multiplier_2_input_a_signal,multiplier_2_input_b_signal,multiplier_3_input_a_signal,multiplier_3_input_b_signal): 211 | """ 212 | DFT complex_multiplier_loader 213 | module used to perform the preliminary addition before the multiplication operations required in complex multiplications 214 | """ 215 | @always_comb 216 | def complex_multiplier_loader_logic(): 217 | # (a+bj)*(c+dj) 218 | multiplier_1_input_a_signal.next = input_a_real #a 219 | multiplier_1_input_b_signal.next = input_b_real+input_b_imag #(c+d) 220 | 221 | multiplier_2_input_a_signal.next = (input_a_real+input_a_imag) #(a+b) 222 | multiplier_2_input_b_signal.next = input_b_imag# (d) 223 | 224 | multiplier_3_input_a_signal.next = (input_a_real-input_a_imag) #(a-b) 225 | multiplier_3_input_b_signal.next = input_b_real #(c) 226 | 227 | return complex_multiplier_loader_logic 228 | 229 | 230 | def complex_multiplier_adder(self,output_real,output_imag,multiplier_1_output,multiplier_2_output,multiplier_3_output): 231 | """ 232 | DFT complex_multiplier_adder 233 | module used to perform the post-multiplication subtractions required in complex multiplications 234 | """ 235 | @always_comb 236 | def complex_multiplier_adder_logic(): 237 | 238 | output_real.next = multiplier_1_output - multiplier_2_output # (c+d)a - (a+b)d = ac-bd 239 | output_imag.next = multiplier_1_output - multiplier_3_output # (c+d)a - (a-b)c = (ad+bc)j 240 | 241 | return complex_multiplier_adder_logic 242 | 243 | def complex_adder(self,output_a_real,output_a_imag,output_a_trigger,input_a_real,input_a_imag,input_a_trigger,input_b_real,input_b_imag,input_b_trigger): 244 | """ 245 | DFT complex_adder 246 | module used to perform complex additions, used in the adder tree after the multiplication stage of the DFT 247 | """ 248 | @always(input_a_trigger,input_b_trigger) 249 | def complex_adder_adding_logic(): 250 | output_a_real.next = input_a_real + input_b_real 251 | output_a_imag.next = input_a_imag + input_b_imag 252 | output_a_trigger.next = not(output_a_trigger) 253 | 254 | return complex_adder_adding_logic#,complex_adder_reset_logic 255 | 256 | def logic(self,input_line_real,input_line_imag,input_trigger,input_enable,output_line_real,output_line_imag,output_trigger,output_enable,reset): 257 | """ 258 | DFT logic method 259 | calls all of the behavioural methods, for conversion purposes as well as all of the supporting modules used to perform those methods 260 | """ 261 | self.twiddle_factor_units = [] #twiddle roms used to store twiddle values 262 | self.twiddle_factor_units_output_real = [] #output signals from twiddle roms 263 | self.twiddle_factor_units_output_imag = [] 264 | 265 | self.multipliers = [] #normal multiplers used in the complex multiplication task 266 | self.multiplier_signals = [] #signals used to communicate within the complex multipliers 267 | 268 | self.complex_multiplier_loaders = [] #units that do the pre-multiplication addition for the complex multiplication operation 269 | self.complex_multiplier_adders = [] #units that do the post-multiplcation addition for the complex multiplication operation 270 | self.multipliers_output_real = [] #output signals from the complex multipliers 271 | self.multipliers_output_imag = [] 272 | 273 | self.complex_adders = [] #complex adder units used to sum outputs input value multiplication with twiddle factors 274 | self.complex_adders_output_real = [] #output signals from the adders 275 | self.complex_adders_output_imag = [] 276 | self.complex_adders_output_trigger = [] #output triggers for adder units, used to trigger the next adder in the set, and reset the previous set 277 | 278 | adder_stages = int(math.log(self.no_inputs)/math.log(2)) #calculating the required size of the adder tree 279 | #creating output triggers for the adders in the tree 280 | for i in range(int(self.no_inputs)-1): self.complex_adders_output_trigger.append(Signal(bool(0)))#,delay=1)) 281 | 282 | #logic to create complex multiplications and twiddle factor units, and wire them up 283 | self.twiddle_factor_units_output_real.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize-1),max=2**(self.multiplier_bitsize-1)))) 284 | 285 | adder_trigger_index = 0 286 | for i in range(self.no_inputs): 287 | self.twiddle_factor_units_output_real.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize-1),max=2**(self.multiplier_bitsize-1)))) 288 | self.twiddle_factor_units.append(self.rom(self.twiddle_factor_units_output_real[-1],self.iteration_count,tuple(map(int,self.tf_real[i*self.no_inputs:i*self.no_inputs+self.no_inputs])))) 289 | 290 | self.twiddle_factor_units_output_imag.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize-1),max=2**(self.multiplier_bitsize-1)))) 291 | self.twiddle_factor_units.append(self.rom(self.twiddle_factor_units_output_imag[-1],self.iteration_count,tuple(map(int,self.tf_imag[i*self.no_inputs:i*self.no_inputs+self.no_inputs])))) 292 | 293 | for j in range(3): #three multipliers needed per complex multiplication 294 | self.multiplier_signals.append(Signal(intbv(0,min=-2**(2*self.multiplier_bitsize-1),max=2**(2*self.multiplier_bitsize-1)))) 295 | for k in range(2): #three signals needed per multipler -> output, input_a, input_b 296 | self.multiplier_signals.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize-1),max=2**(self.multiplier_bitsize-1)))) 297 | 298 | multi_name = "multi_%d_%d_%d" % (i,j,k) 299 | self.multipliers.append(self.multi(self.multiplier_signals[-3],self.multiplier_signals[-2],self.multiplier_signals[-1],self.clk,self.reset,multi_name,self.pull_up)) 300 | 301 | self.complex_multiplier_loaders.append(self.complex_multiplier_loader(self.input_buffer_real[i],self.input_buffer_imag[i],self.twiddle_factor_units_output_real[-1],self.twiddle_factor_units_output_imag[-1],self.multiplier_signals[-8],self.multiplier_signals[-7],self.multiplier_signals[-5],self.multiplier_signals[-4],self.multiplier_signals[-2],self.multiplier_signals[-1])) 302 | 303 | self.multipliers_output_real.append(Signal(intbv(0,min=-2**(2*self.multiplier_bitsize-1),max=2**(2*self.multiplier_bitsize-1)))) 304 | self.multipliers_output_imag.append(Signal(intbv(0,min=-2**(2*self.multiplier_bitsize-1),max=2**(2*self.multiplier_bitsize-1)))) 305 | self.complex_multiplier_adders.append(self.complex_multiplier_adder(self.multipliers_output_real[-1],self.multipliers_output_imag[-1],self.multiplier_signals[-9],self.multiplier_signals[-6],self.multiplier_signals[-3])) 306 | 307 | #creating the first row of the adder tree, i.e. the stage straight after the complex multiplication 308 | if(i%2): #every 2nd value 309 | self.complex_adders_output_real.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 310 | self.complex_adders_output_imag.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 311 | 312 | self.complex_adders.append(self.complex_adder(self.complex_adders_output_real[-1],self.complex_adders_output_imag[-1],self.complex_adders_output_trigger[adder_trigger_index],self.multipliers_output_real[-2],self.multipliers_output_imag[-2],self.processing_iteration,self.multipliers_output_real[-1],self.multipliers_output_imag[-1],self.processing_iteration)) 313 | adder_trigger_index += 1 314 | 315 | 316 | #logic to create adder tree, beyond 1st row 317 | output_offset = 0 318 | adders = self.no_inputs/4 319 | 320 | for j in range(adder_stages-2): 321 | for i in range(adders): 322 | 323 | self.complex_adders_output_real.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 324 | self.complex_adders_output_imag.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 325 | 326 | self.complex_adders.append(self.complex_adder(self.complex_adders_output_real[-1],self.complex_adders_output_imag[-1],self.complex_adders_output_trigger[adder_trigger_index],self.complex_adders_output_real[output_offset],self.complex_adders_output_imag[output_offset],self.complex_adders_output_trigger[output_offset],self.complex_adders_output_real[output_offset+1],self.complex_adders_output_imag[output_offset+1],self.complex_adders_output_trigger[output_offset+1])) 327 | adder_trigger_index += 1 328 | output_offset += 2 329 | 330 | adders = adders/2 331 | 332 | #last stage of output signals 333 | self.complex_adders_output_real.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 334 | self.complex_adders_output_imag.append(Signal(intbv(0,min=-2**(self.multiplier_bitsize*2+adder_stages),max=2**(self.multiplier_bitsize*2+adder_stages)))) 335 | 336 | self.complex_adders.append(self.complex_adder(self.complex_adders_output_real[-1],self.complex_adders_output_imag[-1],self.complex_adders_output_trigger[adder_trigger_index],self.complex_adders_output_real[output_offset],self.complex_adders_output_imag[output_offset],self.complex_adders_output_trigger[output_offset],self.complex_adders_output_real[output_offset+1],self.complex_adders_output_imag[output_offset+1],self.complex_adders_output_trigger[output_offset+1])) 337 | 338 | #various logic instances created 339 | tf_unit_insts = self.twiddle_factor_units 340 | multi_insts = self.multipliers 341 | complex_multi_loader_insts = self.complex_multiplier_loaders 342 | complex_multi_adder_insts = self.complex_multiplier_adders 343 | complex_adder_insts = self.complex_adders 344 | 345 | #processing_logic = self.processing() 346 | baseclass_logic = Actor.Actor.logic(self) 347 | 348 | return instances() 349 | 350 | def model(self,input_values_real,input_values_imag): 351 | """ 352 | DFT model method 353 | performs the same operation as the processing method of the actor, but does it upon a Python list 354 | 355 | Parameters: 356 | input_values_real -> input list of the real values 357 | input_values_imag -> input list of the imaginary values 358 | 359 | Output: 360 | [output real values list, output imaginary values list] 361 | """ 362 | output_values_real = [] 363 | output_values_imag = [] 364 | 365 | for k in range(len(input_values_real)): 366 | output_values_real.append([]) 367 | output_values_imag.append([]) 368 | for i in range(len(input_values_real[k])): 369 | temp_real = 0 370 | temp_imag = 0 371 | for j in range(self.no_inputs): 372 | temp_real += (input_values_real[k][j]*self.tf_real[i*self.no_inputs+j] - input_values_imag[k][j]*self.tf_imag[i*self.no_inputs+j]) 373 | temp_imag += (input_values_real[k][j]*self.tf_imag[i*self.no_inputs+j] + input_values_imag[k][j]*self.tf_real[i*self.no_inputs+j]) 374 | 375 | output_values_real[-1].append(temp_real) 376 | output_values_imag[-1].append(temp_imag) 377 | 378 | return [output_values_real,output_values_imag] 379 | 380 | 381 | -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/DivideAndConquer.py: -------------------------------------------------------------------------------- 1 | #Divide and Conquer class 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import Actor 7 | 8 | class DivideAndConquer(Actor.Actor): 9 | name = "DivideAndConquer" 10 | 11 | input_enable_2 = Signal(bool(0)) 12 | 13 | no_outputs_2 = 0 #2nd Output parameters 14 | output_count_2 = Signal(intbv(0)) 15 | output_bitsize_2 = 0 16 | 17 | output_line_real_2 = Signal(intbv(0)) #2nd Output signals 18 | output_line_imag_2 = Signal(intbv(0)) 19 | output_trigger_2 = Signal(bool(0)) 20 | output_enable_2 = Signal(bool(0)) 21 | 22 | output_buffer_real_2 = [] #2nd Output buffers 23 | output_buffer_imag_2 = [] 24 | 25 | twiddle_bits = 0 26 | twiddle_factors_real = [] 27 | twiddle_factors_imag = [] 28 | 29 | processing_input_enable_2 = Signal(bool(1)) #2nd internal signals 30 | processing_output_enable_2 = Signal(bool(1)) 31 | processing_output_trigger_2 = Signal(bool(0)) 32 | 33 | twiddle_rom_line_real = Signal(intbv(0)) 34 | twiddle_rom_line_imag = Signal(intbv(0)) 35 | 36 | tf_real = () 37 | tf_imag = () 38 | 39 | transmitting_flag_2 = Signal(bool(0)) 40 | processing_flag_2 = Signal(bool(0)) 41 | 42 | def __init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,output_line_real_2,output_line_imag_2,output_trigger_2,output_enable_2,no_outputs_2,reset,clk,twiddle_bits=0,tf_real=[],tf_imag=[],input_bitsize=0,output_bitsize=0,output_bitsize_2=0):#,verbosity=False): 43 | """ 44 | DivideAndConquer Constructor 45 | Parameters: 46 | *Control Signals* 47 | clk -> clock signal, used to synchronise behaviour across the module 48 | reset -> asynchronous reset line, used to restart the behaviour of the module 49 | 50 | *Data Signals* 51 | **Input** 52 | input_line_real -> input data line for the real part of the input signal 53 | input_line_imag -> input data line for the imaginary part of the input signal 54 | input_trigger -> input signal (1 bit) line used to indicate that data may be read into the actor 55 | input_enable -> actually an output signal line used to indicate that the actor is ready to read new data 56 | 57 | **Output** 58 | output_line_real -> output data line for the real part of the output signal 59 | output_line_imag -> output data line for the imaginary part of the output signal 60 | output_trigger -> output signal (1 bit) line used to indicate that data is ready to be read from the actor 61 | output_enable -> actually an input signal line used to indicate to the module that the following actor is ready to read from it 62 | 63 | output_line_real_2 -> output data line for the real part of the 2nd output signal 64 | output_line_imag_2 -> output data line for the imaginary part of the 2nd output signal 65 | output_trigger_2 -> output signal (1 bit) line used to indicate that the 2nd set of output data is ready to be read from the actor 66 | output_enable_2 -> actually an input signal line used to indicate to the module that the following actor is ready to read from the 2nd set of the output data 67 | 68 | *Normal Parameters* 69 | no_inputs -> integer value specifying how many samples need to be read into the actor before it processes that data 70 | no_outputs -> integer value specifying how many samples will be produced in the first dataset upon the completion of its processing activity 71 | no_outputs_2 -> integer value specifying how many samples will be produced in the second dataset upon the completion of its processing activity 72 | input_bitsize -> the bit size of each of the input data lines 73 | output_bitsize -> the bit size of each of the output data lines 74 | output_bitsize_2 -> the bit size of each of the output data lines for the second dataset 75 | twiddle_bits -> the bit size of the twiddle factors used in the divide and conquer Operation 76 | tf_real -> a list containing the real parts of the twiddle factors required by the divide and conquer operation 77 | tf_imag -> a list containing the imaginary parts of the twiddle factors required by the divide and conquer operation 78 | 79 | """ 80 | Actor.Actor.__init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,input_bitsize=input_bitsize,output_bitsize=output_bitsize,reset=reset,clk=clk)#,verbosity=verbosity) 81 | 82 | self.no_outputs_2 = no_outputs_2 83 | if(self.no_outputs_2): self.output_count_2 = Signal(intbv(0,min=0,max=self.no_outputs_2+1)) #internal count variable 84 | self.output_bitsize_2 = output_bitsize_2 85 | 86 | self.output_line_real_2 = output_line_real_2 87 | self.output_line_imag_2 = output_line_imag_2 88 | self.output_trigger_2 = output_trigger_2 89 | self.output_enable_2 = output_enable_2 90 | 91 | self.output_bitsize_2 = output_bitsize_2 92 | if(self.output_bitsize_2): 93 | self.output_buffer_real_2 = [Signal(intbv(0,min=-2**(self.output_bitsize_2-1),max=2**(self.output_bitsize_2-1))) for i in range(no_outputs_2)] 94 | self.output_buffer_imag_2 = [Signal(intbv(0,min=-2**(self.output_bitsize_2-1),max=2**(self.output_bitsize_2-1))) for i in range(no_outputs_2)] 95 | else: 96 | self.output_buffer_real_2 = [Signal(intbv(0)) for i in range(no_outputs_2)] 97 | self.output_buffer_imag_2 = [Signal(intbv(0)) for i in range(no_outputs_2)] 98 | 99 | self.twiddle_bits = twiddle_bits 100 | self.twiddle_factors_real = [Signal(intbv(0)) for i in range(no_outputs_2)] 101 | self.twiddle_factors_imag = [Signal(intbv(0)) for i in range(no_outputs_2)] 102 | 103 | if(self.twiddle_bits): 104 | self.twiddle_factors_real = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(no_outputs_2)] 105 | self.twiddle_factors_imag = [Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) for i in range(no_outputs_2)] 106 | 107 | self.twiddle_rom_line_real = Signal(intbv(0)) 108 | self.twiddle_rom_line_imag = Signal(intbv(0)) 109 | 110 | if(self.twiddle_bits): 111 | self.twiddle_rom_line_real = Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) 112 | self.twiddle_rom_line_imag = Signal(intbv(0,min=-2**(self.twiddle_bits-1),max=2**(self.twiddle_bits-1))) 113 | 114 | self.processing_input_enable_2 = Signal(bool(1)) 115 | self.processing_output_enable_2 = Signal(bool(1)) 116 | self.processing_output_trigger_2 = Signal(bool(0)) 117 | self.transmitting_flag_2 = Signal(bool(0)) 118 | 119 | self.twiddle_rom_addr_real = Signal(intbv(0,min=0,max=self.no_outputs+1)) 120 | self.twiddle_rom_addr_imag = Signal(intbv(0,min=0,max=self.no_outputs+1)) 121 | 122 | self.tf_real = tuple(map(int,tf_real)) 123 | self.tf_imag = tuple(map(int,tf_imag)) 124 | 125 | self.transmitting_flag_2 = Signal(bool(0)) 126 | self.processing_flag_2 = Signal(bool(0)) 127 | 128 | def receiving(self): 129 | """ 130 | DivideAndConquer receiving behaviour 131 | primarily works with the actor input and control signals. Note that although this behaviour appears extremely similar to the Actor receiving behaviour, it requires both processing behaviours to be complete, and so the logic is different. 132 | """ 133 | input_trigger = self.input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 134 | processing_input_enable = self.processing_input_enable 135 | processing_input_enable_2 = self.processing_input_enable_2 136 | input_count = self.input_count 137 | no_inputs = self.no_inputs 138 | no_outputs = self.no_outputs 139 | input_buffer_real = self.input_buffer_real 140 | input_buffer_imag = self.input_buffer_imag 141 | input_line_real = self.input_line_real 142 | input_line_imag = self.input_line_imag 143 | input_enable = self.input_enable 144 | processing_input_trigger = self.processing_input_trigger 145 | reset = self.reset 146 | receiving_flag = self.receiving_flag 147 | clk = self.clk 148 | stall_flag = Signal(bool(0)) 149 | 150 | twiddle_rom_addr_real = self.twiddle_rom_addr_real 151 | twiddle_rom_addr_imag = self.twiddle_rom_addr_imag 152 | twiddle_rom_line_real = self.twiddle_rom_line_real 153 | twiddle_rom_line_imag = self.twiddle_rom_line_imag 154 | twiddle_factors_real = self.twiddle_factors_real 155 | twiddle_factors_imag = self.twiddle_factors_imag 156 | 157 | @always(clk.posedge,reset.posedge) 158 | def receiving_logic(): 159 | if(reset==1): #asynchronous reset 160 | input_count.next = 0 161 | input_enable.next = 1 162 | processing_input_trigger.next = 0 163 | receiving_flag.next = 0 164 | stall_flag.next = 0 165 | twiddle_rom_addr_real.next = 0 166 | twiddle_rom_addr_imag.next = 0 167 | 168 | elif(receiving_flag==1): 169 | if(input_count<(no_inputs)): #Populating the input buffer 170 | input_buffer_real[int(input_count)].next = input_line_real 171 | input_buffer_imag[int(input_count)].next = input_line_imag 172 | 173 | if(input_count<(no_outputs)): #Also populate the twiddle factor buffer 174 | twiddle_factors_real[input_count].next = twiddle_rom_line_real 175 | twiddle_factors_imag[input_count].next = twiddle_rom_line_imag 176 | 177 | if(input_count<(no_outputs-1)): 178 | twiddle_rom_addr_real.next = input_count+1 179 | twiddle_rom_addr_imag.next = input_count+1 180 | 181 | else: 182 | twiddle_rom_addr_real.next = 0 183 | twiddle_rom_addr_imag.next = 0 184 | 185 | input_count.next = input_count + 1 186 | 187 | else: #When the input buffer is full, copy the last value, trigger the processing and stall the input 188 | input_count.next = 0 189 | input_enable.next = 0 190 | processing_input_trigger.next = 1 191 | receiving_flag.next = 0 192 | stall_flag.next = 1 193 | 194 | else: 195 | if(stall_flag): #stall for a clock cycle 196 | stall_flag.next = 0 197 | 198 | elif((input_trigger==1) and (processing_input_enable==1) and (processing_input_enable_2==1)): #Note the requirement for both processing input enables. 199 | receiving_flag.next = 1 200 | input_enable.next = 0 201 | processing_input_trigger.next = 0 202 | 203 | elif((processing_input_enable==1) and (processing_input_enable_2==1)): # if there is no data waiting to be read and the internal processing is done, indicate that internal processing may start 204 | input_enable.next = 1 205 | processing_input_trigger.next = 0 206 | 207 | return receiving_logic 208 | 209 | def processing(self): 210 | """ 211 | DivideAndConquer processing behaviour 212 | primarily works with the input and two outputs buffers and the internal control signals 213 | """ 214 | processing_input_trigger = self.processing_input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 215 | processing_output_enable = self.processing_output_enable 216 | processing_output_enable_2 = self.processing_output_enable_2 217 | output_buffer_real = self.output_buffer_real 218 | output_buffer_imag = self.output_buffer_imag 219 | output_buffer_real_2 = self.output_buffer_real_2 220 | output_buffer_imag_2 = self.output_buffer_imag_2 221 | input_buffer_real = self.input_buffer_real 222 | input_buffer_imag = self.input_buffer_imag 223 | processing_output_trigger = self.processing_output_trigger 224 | processing_output_trigger_2 = self.processing_output_trigger_2 225 | input_enable = self.input_enable 226 | twiddle_factors_real = self.twiddle_factors_real 227 | twiddle_factors_imag = self.twiddle_factors_imag 228 | no_inputs = self.no_inputs 229 | no_outputs = self.no_outputs 230 | processing_input_enable = self.processing_input_enable 231 | processing_input_enable_2 = self.processing_input_enable_2 232 | reset = self.reset 233 | clk = self.clk 234 | busy = Signal(bool(0)) 235 | busy_2 = Signal(bool(0)) 236 | stall_flag = Signal(bool(0)) 237 | stall_flag_2 = Signal(bool(0)) 238 | processing_flag = self.processing_flag 239 | processing_flag_2 = self.processing_flag_2 240 | twiddle_bits = self.twiddle_bits 241 | 242 | @always(reset.posedge,clk.posedge) 243 | def processing_logic(): #Processing logic for the upper part of the divide and conquer operation, which is a sum operation 244 | if(reset==1): 245 | processing_output_trigger.next = 0 246 | processing_input_enable.next = 1 247 | processing_flag.next = 0 248 | busy.next = 1 249 | stall_flag.next = 0 250 | 251 | elif(processing_flag==1): #Only process if the trigger and enable line are high 252 | if(busy==1): 253 | for i in range(no_outputs): #The upper part of the divide and conquer is the sum operation 254 | output_buffer_real[i].next = ((input_buffer_real[i]+input_buffer_real[i+no_outputs]) << (twiddle_bits-1)) 255 | output_buffer_imag[i].next = ((input_buffer_imag[i]+input_buffer_imag[i+no_outputs]) << (twiddle_bits-1)) 256 | busy.next = 0 257 | 258 | else: 259 | processing_output_trigger.next = 1 260 | processing_input_enable.next = 1 261 | processing_flag.next = 0 262 | busy.next = 1 263 | stall_flag.next = 1 264 | 265 | else: 266 | if(stall_flag==1): stall_flag.next = 0 267 | 268 | elif((processing_input_trigger==1) and (processing_output_enable==1)): 269 | processing_flag.next = 1 270 | busy.next = 1 271 | processing_input_enable.next = 0 272 | processing_output_trigger.next = 0 273 | 274 | elif(processing_output_enable==1): 275 | processing_output_trigger.next = 0 276 | 277 | elif(processing_input_trigger==1): 278 | processing_input_enable.next = 0 279 | 280 | @always(reset.posedge,clk.posedge) 281 | def processing_logic_2(): #Processing logic for the lower part of the divide and conquer operation, which is a difference and then multiply operation 282 | if(reset): 283 | processing_output_trigger_2.next = 0 284 | processing_input_enable_2.next = 1 285 | processing_flag_2.next = 0 286 | busy_2.next = 1 287 | stall_flag_2.next = 0 288 | 289 | elif(processing_flag_2==1): #Only process if the trigger and enable line are high 290 | if(busy_2): 291 | for i in range(no_outputs): #difference and multiply by the twiddle factor operation. 292 | temp_real = (input_buffer_real[i]-input_buffer_real[i+no_outputs]) 293 | temp_imag = (input_buffer_imag[i]-input_buffer_imag[i+no_outputs]) 294 | output_buffer_real_2[i].next = (temp_real*twiddle_factors_real[i]-temp_imag*twiddle_factors_imag[i]) 295 | output_buffer_imag_2[i].next = (temp_imag*twiddle_factors_real[i]+temp_real*twiddle_factors_imag[i]) 296 | 297 | busy_2.next = 0 298 | 299 | else: 300 | processing_output_trigger_2.next = 1 301 | processing_input_enable_2.next = 1 302 | processing_flag_2.next = 0 303 | busy_2.next = 1 304 | stall_flag_2.next = 1 305 | 306 | else: 307 | if(stall_flag_2): stall_flag_2.next = 0 308 | 309 | elif((processing_input_trigger==1) and (processing_output_enable_2==1)): 310 | processing_flag_2.next = 1 311 | busy_2.next = 1 312 | processing_input_enable_2.next = 0 313 | processing_output_trigger_2.next = 0 314 | 315 | elif(processing_output_enable_2==1): 316 | processing_output_trigger_2.next = 0 317 | 318 | elif(processing_input_trigger==1): 319 | processing_input_enable_2.next = 0 320 | 321 | return instances() 322 | 323 | def transmiting(self): 324 | """ 325 | DivideAndConquer transmitting behaviour 326 | primarily works with the actor output and control signals. It calls the base Actor class transmitting method, and adds additional transmitting behaviour for the second output buffer. 327 | """ 328 | baseclass_transmiting_inst = Actor.Actor.transmiting(self) #call the base class method transmitting method for the top output set 329 | 330 | output_enable = self.output_enable 331 | 332 | output_line_real_2 = self.output_line_real_2 333 | output_line_imag_2 = self.output_line_imag_2 334 | processing_output_trigger_2 = self.processing_output_trigger_2 335 | output_enable_2 = self.output_enable_2 336 | 337 | output_count_2 = self.output_count_2 338 | no_outputs_2 = self.no_outputs_2 339 | 340 | output_buffer_real_2 = self.output_buffer_real_2 341 | output_buffer_imag_2 = self.output_buffer_imag_2 342 | processing_output_enable_2 = self.processing_output_enable_2 343 | output_trigger_2 = self.output_trigger_2 344 | reset = self.reset 345 | transmitting_flag_2 = self.transmitting_flag_2 346 | clk = self.clk 347 | stall_flag_2 = Signal(bool(0)) 348 | pending_flag_2 = Signal(bool(0)) 349 | 350 | @always(clk.posedge,reset.posedge) 351 | def transmiting_logic_2(): 352 | if(reset==1): #asynchronous reset 353 | output_count_2.next = 0 354 | output_line_real_2.next = 0 355 | output_line_imag_2.next = 0 356 | processing_output_enable_2.next = 1 357 | output_trigger_2.next = 0 358 | transmitting_flag_2.next = 0 359 | stall_flag_2.next = 1 360 | pending_flag_2.next = 1 361 | 362 | elif(transmitting_flag_2==1): 363 | if(output_count_2<(no_outputs_2)): 364 | output_line_real_2.next = output_buffer_real_2[int(output_count_2)] #Outputing values 365 | output_line_imag_2.next = output_buffer_imag_2[int(output_count_2)] 366 | processing_output_enable_2.next = 0 367 | output_count_2.next = output_count_2 + 1 368 | 369 | #transmitting_flag.next = 0 370 | 371 | else: #When the output buffer has been fully transmitted... 372 | output_trigger_2.next = 0 #indicate that there are no new values available 373 | output_count_2.next = 0 374 | transmitting_flag_2.next = 0 375 | processing_output_enable_2.next = 1 #indicate that processing may run again 376 | stall_flag_2.next = 1 377 | 378 | else: 379 | if(stall_flag_2==1): stall_flag_2.next = 0 #stall for a clock cycle 380 | 381 | elif((output_enable_2==1) and (processing_output_trigger_2==1)): #if output is allowed and processing is complete, start the transmitting behaviour 382 | transmitting_flag_2.next = 1 383 | output_trigger_2.next = 1 384 | processing_output_enable_2.next = 0 385 | pending_flag_2.next = 0 386 | 387 | elif((output_enable_2==1) and (pending_flag_2 != 1)): #if output is allowed and there is no output data pending, indicate that processing can occur 388 | processing_output_enable_2.next = 1 389 | 390 | elif(processing_output_trigger_2==1): #if processing is complete, but output is not allowed, raise the pending flag and stall any future processing 391 | pending_flag_2.next = 1 392 | processing_output_enable_2.next = 0 393 | 394 | return instances() 395 | 396 | def rom(self,dout, addr, CONTENT): 397 | """ 398 | DivideAndConquer rom behaviour 399 | this independent module is used to provide the ROM for the twiddle factors that are required 400 | """ 401 | @always_comb 402 | def read(): 403 | dout.next = CONTENT[int(addr)] 404 | 405 | return read 406 | 407 | def logic(self): 408 | """ 409 | DivideAndConquer logic method 410 | calls all of the behavioural methods, for conversion purposes 411 | """ 412 | baseclass_logic = Actor.Actor.logic(self) #Calls the behavioural methods by calling the Base Class Actor logic method 413 | 414 | twiddle_rom_real_inst = self.rom(self.twiddle_rom_line_real,self.twiddle_rom_addr_real,self.tf_real) #Creates a rom for the real and imaginary parts of the twiddle factors 415 | twiddle_rom_imag_inst = self.rom(self.twiddle_rom_line_imag,self.twiddle_rom_addr_imag,self.tf_imag) 416 | 417 | return instances() 418 | 419 | def model(self,input_values_real,input_values_imag): 420 | """ 421 | DivideAndConquer model method 422 | performs the same operation as the processing method of the actor, but does it upon a Python list 423 | 424 | Parameters: 425 | input_values_real -> input list of the real values 426 | input_values_imag -> input list of the imaginary values 427 | 428 | Output: 429 | [output real values list, output imaginary values list,output real values list for second dataset, output imaginary values list for second dataset] 430 | """ 431 | output_values_real = [] 432 | output_values_imag = [] 433 | output_values_real_2 = [] 434 | output_values_imag_2 = [] 435 | 436 | for i_v in range(len(input_values_real)): 437 | output_values_imag.append([]) 438 | output_values_imag_2.append([]) 439 | output_values_real.append([]) 440 | output_values_real_2.append([]) 441 | for i in range(len(input_values_real[i_v])/2): 442 | output_values_real[-1].append((input_values_real[i_v][i]+input_values_real[i_v][len(input_values_real[i_v])/2+i]) << (self.twiddle_bits-1)) 443 | output_values_imag[-1].append((input_values_imag[i_v][i]+input_values_imag[i_v][len(input_values_imag[i_v])/2+i]) << (self.twiddle_bits-1)) 444 | 445 | temp_real = (input_values_real[i_v][i]-input_values_real[i_v][len(input_values_real[i_v])/2+i]) 446 | temp_imag = (input_values_imag[i_v][i]-input_values_imag[i_v][len(input_values_imag[i_v])/2+i]) 447 | 448 | output_values_real_2[-1].append(temp_real*self.tf_real[i]-temp_imag*self.tf_imag[i]) 449 | output_values_imag_2[-1].append(temp_real*self.tf_imag[i]+temp_imag*self.tf_real[i]) 450 | 451 | return [output_values_real,output_values_imag,output_values_real_2,output_values_imag_2] 452 | -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/Mux.py: -------------------------------------------------------------------------------- 1 | #Mux class 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import Actor,math 7 | 8 | class Mux(Actor.Actor): 9 | name = "Mux" 10 | 11 | no_input_lines = 0 #Internal variables 12 | input_line_no = Signal(intbv(0)) 13 | 14 | input_line_real_array = [] #lists of input signals 15 | input_line_imag_array = [] 16 | input_trigger_array = [] 17 | input_enable_array = [] 18 | 19 | muxes = [] #this list will hold the mux 2 instances that make up the mux 20 | muxes_signal_real = [] #these lists represent the internal signals that the mux 2 instances use to make up the N part mux 21 | muxes_signal_imag = [] 22 | muxes_signal_trigger = [] 23 | muxes_signal_enable = [] 24 | 25 | def __init__(self,input_line_real_array,input_line_imag_array,input_trigger_array,input_enable_array,no_inputs,no_input_lines,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,reset,clk,input_bitsize=0,output_bitsize=0): 26 | """ 27 | Mux Constructor 28 | Parameters: 29 | *Control Signals* 30 | clk -> clock signal, used to synchronise behaviour across the module 31 | reset -> asynchronous reset line, used to restart the behaviour of the module 32 | 33 | *Data Signals* 34 | **Input** 35 | input_line_real_array -> list of input data lines for the real part of the input signals 36 | input_line_imag_array -> list of input data lines for the imaginary part of the input signals 37 | input_trigger_array -> list of input signals (1 bit) line used to indicate that data may be read into the actor 38 | input_enable_array -> list of what is actually output signal lines used to indicate that the actor is ready to read new data 39 | 40 | **Output** 41 | output_line_real -> output data line for the real part of the output signal 42 | output_line_imag -> output data line for the imaginary part of the output signal 43 | output_trigger -> output signal (1 bit) line used to indicate that data is ready to be read from the actor 44 | output_enable -> actually an input signal line used to indicate to the module that the following actor is ready to read from it 45 | 46 | *Normal Parameters* 47 | no_inputs -> integer value specifying how many samples need to be read into the actor before it processes that data 48 | no_outputs -> integer value specifying how many samples will be produced upon the completion of its processing activity 49 | input_bitsize -> the size of each of the input data lines 50 | output_bitsize -> the size of each of the output data line 51 | 52 | """ 53 | #Appending the output signal (i.e. the input to the trigger) to mux signal lists 54 | self.muxes = [] #this list will hold the mux 2 instances that make up the mux 55 | self.muxes_signal_real = [] #these lists represent the internal signals that the mux 2 instances use to make up the N part mux 56 | self.muxes_signal_imag = [] 57 | self.muxes_signal_trigger = [] 58 | self.muxes_signal_enable = [] 59 | 60 | self.muxes_signal_real.append(Signal(intbv(0,min=-2**(input_bitsize-1),max=2**(input_bitsize-1)))) #these lists represent the internal signals that the mux 2 instances use to make up the N part mux 61 | self.muxes_signal_imag.append(Signal(intbv(0,min=-2**(input_bitsize-1),max=2**(input_bitsize-1)))) 62 | self.muxes_signal_trigger.append(Signal(bool(0))) 63 | self.muxes_signal_enable.append(Signal(bool(1))) 64 | 65 | #The base class constructor, with the output from the muxes tree set to be the input 66 | Actor.Actor.__init__(self,self.muxes_signal_real[0],self.muxes_signal_imag[0],self.muxes_signal_trigger[0],self.muxes_signal_enable[0],no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,input_bitsize=input_bitsize,output_bitsize=output_bitsize,reset=reset,clk=clk) 67 | 68 | self.no_input_lines = no_input_lines #Internal variables 69 | self.input_line_no = Signal(intbv(0)) 70 | if(self.no_input_lines): self.input_line_no = Signal(intbv(0,min=0,max=self.no_input_lines+1)) 71 | 72 | self.input_line_real_array = input_line_real_array #Input lists of signals 73 | self.input_line_imag_array = input_line_imag_array 74 | self.input_trigger_array = input_trigger_array 75 | self.input_enable_array = input_enable_array 76 | 77 | def receiving(self): 78 | """ 79 | Mux receiving behaviour 80 | primarily works with the actor input and control signals 81 | """ 82 | input_trigger = self.input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 83 | processing_input_enable = self.processing_input_enable 84 | input_count = self.input_count 85 | no_inputs = self.no_inputs 86 | reset = self.reset 87 | no_input_lines = self.no_input_lines 88 | input_line_no = self.input_line_no 89 | clk = self.clk 90 | receiving_flag = self.receiving_flag 91 | 92 | baseclass_receiving_logic = Actor.Actor.receiving(self) #calling the Actor base class receiving behaviour 93 | 94 | @always(clk.posedge,reset.posedge) #Iteration logic used to point the input to the next mux when the previous data set is complete 95 | def receiving_logic_2(): 96 | if(reset==1): #reset logic 97 | input_line_no.next = 0 98 | 99 | elif((input_trigger==1) and (processing_input_enable==1)): #Accept input only if the processing input enable and trigger are high 100 | if((input_line_no<(no_input_lines)) and (input_count>=(no_inputs-1))): 101 | input_line_no.next = input_line_no + 1 #point the mux logic to the next set of input lines 102 | 103 | return instances() 104 | 105 | def mux2(self,a_real,a_imag,a_trigger,a_enable,b_real,b_imag,b_trigger,b_enable,z_real,z_imag,z_trigger,z_enable,sel,clk): 106 | """ 107 | Simple 2 port mux used to build the larger mux 108 | """ 109 | @always_comb 110 | def mux2_logic(): #Simple 2 input mux used to build N-port muxes (N%2=0) 111 | if(sel==0): 112 | z_real.next = a_real 113 | z_imag.next = a_imag 114 | z_trigger.next = a_trigger 115 | a_enable.next = z_enable 116 | 117 | else: 118 | z_real.next = b_real 119 | z_imag.next = b_imag 120 | z_trigger.next = b_trigger 121 | b_enable.next = z_enable 122 | 123 | return instances() 124 | 125 | def logic(self): 126 | """ 127 | Mux logic method 128 | calls all of the behavioural methods and creates a mux tree that connects into the behavioural messages 129 | """ 130 | #for loop for creating all of the 2 port muxes required 131 | output_offset = 0 #Variable for tracking where the output lines from the muxes will be in the list 132 | index_slice = int(math.log(self.no_input_lines)/math.log(2))-1 #Variable for tracking the bit which will be the select for a particular mux 133 | for i in range(int(math.log(self.no_input_lines)/math.log(2))-1): 134 | print 2**i 135 | for j in range(2**i): #Each stage has 2^(stage no) muxes 136 | for k in range(2): #Each mux has 2 input signals 137 | self.muxes_signal_real.append(Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1)))) 138 | self.muxes_signal_imag.append(Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1)))) 139 | self.muxes_signal_trigger.append(Signal(bool(0))) 140 | self.muxes_signal_enable.append(Signal(bool(0))) 141 | 142 | #Mux construction, using two input signals just generated and a signal previous added to the list 143 | self.muxes.append(self.mux2(self.muxes_signal_real[-2],self.muxes_signal_imag[-2],self.muxes_signal_trigger[-2],self.muxes_signal_enable[-2],self.muxes_signal_real[-1],self.muxes_signal_imag[-1],self.muxes_signal_trigger[-1],self.muxes_signal_enable[-1],self.muxes_signal_real[output_offset+j],self.muxes_signal_imag[output_offset+j],self.muxes_signal_trigger[output_offset+j],self.muxes_signal_enable[output_offset+j],self.input_line_no(index_slice),self.clk)) 144 | 145 | output_offset += 2**i #offset is basically the sum of the muxes up to the end of the previous stage 146 | index_slice -= 1 #index slice moves from left to right, as output grows by factor 2 147 | 148 | #for loop for connecting lists of input signals to the inputs to the outermost stages of the mux 149 | index = self.no_input_lines/2 150 | for i in range(index): 151 | self.muxes.append(self.mux2(self.input_line_real_array[i*2],self.input_line_imag_array[i*2],self.input_trigger_array[i*2],self.input_enable_array[i*2],self.input_line_real_array[i*2+1],self.input_line_imag_array[i*2+1],self.input_trigger_array[i*2+1],self.input_enable_array[i*2+1],self.muxes_signal_real[output_offset+i],self.muxes_signal_imag[output_offset+i],self.muxes_signal_trigger[output_offset+i],self.muxes_signal_enable[output_offset+i],self.input_line_no(index_slice),self.clk)) 152 | 153 | muxes_inst = self.muxes #list of the muxes created 154 | baseclass_logic = Actor.Actor.logic(self) #logic from the baseclass 155 | 156 | return instances() 157 | 158 | def model(self,input_values_real,input_values_imag): #takes lists of lists as arguments 159 | """ 160 | Mux model method 161 | performs the same operation as the processing method of the mux, but does it upon a Python list. In this case it creates one long list of the many sublists supplied to it. 162 | 163 | Parameters: 164 | input_values_real -> input list of the real values 165 | input_values_imag -> input list of the imaginary values 166 | 167 | Output: 168 | [output real values list, output imaginary values list] 169 | """ 170 | output_values_real = [] 171 | output_values_imag = [] 172 | 173 | for i in range(len(input_values_real)): 174 | output_values = Actor.Actor.model(self,[input_values_real[i]],[input_values_imag[i]]) 175 | output_values_real.append(output_values[0][0]) 176 | output_values_imag.append(output_values[1][0]) 177 | 178 | return [output_values_real,output_values_imag] #returns lists of lists -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/Unscrambler.py: -------------------------------------------------------------------------------- 1 | #Unscrambler class 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import Actor 7 | 8 | class Unscrambler(Actor.Actor): 9 | name = "Unscrambler" 10 | 11 | index_mapping = () 12 | index_mapping_array = [] 13 | 14 | index_addr = Signal(intbv(0)) 15 | index_output = Signal(intbv(0)) 16 | 17 | processing_count = Signal(intbv(0)) 18 | 19 | def __init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,reset,clk,index_mapping,input_bitsize=0,output_bitsize=0,verbosity=False): 20 | """ 21 | Unscrambler Constructor 22 | Parameters: 23 | *Control Signals* 24 | clk -> clock signal, used to synchronise behaviour across the module 25 | reset -> asynchronous reset line, used to restart the behaviour of the module 26 | 27 | *Data Signals* 28 | **Input** 29 | input_line_real -> input data line for the real part of the input signal 30 | input_line_imag -> input data line for the imaginary part of the input signal 31 | input_trigger -> input signal (1 bit) line used to indicate that data may be read into the actor 32 | input_enable -> actually an output signal line used to indicate that the actor is ready to read new data 33 | 34 | **Output** 35 | output_line_real -> output data line for the real part of the output signal 36 | output_line_imag -> output data line for the imaginary part of the output signal 37 | output_trigger -> output signal (1 bit) line used to indicate that data is ready to be read from the actor 38 | output_enable -> actually an input signal line used to indicate to the module that the following actor is ready to read from it 39 | 40 | *Normal Parameters* 41 | no_inputs -> integer value specifying how many samples need to be read into the actor before it processes that data 42 | no_outputs -> integer value specifying how many samples will be produced upon the completion of its processing activity 43 | input_bitsize -> the bit size of each of the input data lines 44 | output_bitsize -> the bit size of each of the output data line 45 | index_mapping -> the list containing the index remapping of the data being passed through the module 46 | 47 | """ 48 | Actor.Actor.__init__(self,input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,input_bitsize=input_bitsize,output_bitsize=output_bitsize,clk=clk,reset=reset) #Call to base Actor class 49 | 50 | if(self.input_bitsize): 51 | self.input_buffer_real = [Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1))) for i in range(no_outputs)] 52 | self.input_buffer_imag = [Signal(intbv(0,min=-2**(self.input_bitsize-1),max=2**(self.input_bitsize-1))) for i in range(no_outputs)] 53 | else: 54 | self.input_buffer_real = [Signal(intbv(0)) for i in range(no_inputs)] 55 | self.input_buffer_imag = [Signal(intbv(0)) for i in range(no_inputs)] 56 | 57 | self.index_mapping = index_mapping 58 | self.index_addr = Signal(intbv(0,min=0,max=self.no_outputs+1)) 59 | self.index_output = Signal(intbv(0,min=0,max=self.no_outputs+1)) 60 | 61 | for i in range(self.no_outputs): self.index_mapping_array.append(Signal(intbv(0,min=0,max=self.no_outputs+1))) 62 | 63 | self.processing_count = Signal(intbv(0,min=0,max=no_outputs+1)) 64 | 65 | def receiving(self): 66 | """ 67 | Unscrambler receiving method 68 | primarily works with input data signals 69 | """ 70 | input_trigger = self.input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 71 | processing_input_enable = self.processing_input_enable 72 | input_count = self.input_count 73 | no_inputs = self.no_inputs 74 | input_buffer_real = self.input_buffer_real 75 | input_buffer_imag = self.input_buffer_imag 76 | input_line_real = self.input_line_real 77 | input_line_imag = self.input_line_imag 78 | input_enable = self.input_enable 79 | processing_input_trigger = self.processing_input_trigger 80 | reset = self.reset 81 | receiving_flag = self.receiving_flag 82 | stall_flag = Signal(bool(0)) 83 | clk = self.clk 84 | no_outputs = self.no_outputs 85 | 86 | index_mapping_array = self.index_mapping_array 87 | index_addr = self.index_addr 88 | index_output = self.index_output 89 | processing_count = self.processing_count 90 | 91 | @always(clk.posedge,reset.posedge) 92 | def receiving_logic(): 93 | if(reset==1): 94 | input_count.next = 0 95 | input_enable.next = 1 96 | processing_input_trigger.next = 0 97 | receiving_flag.next = 0 98 | stall_flag.next = 0 99 | index_addr.next = 0 100 | 101 | elif(receiving_flag==1): 102 | if(input_count<(no_inputs)): #Populating the input buffer 103 | if(index_addr<(no_outputs-1)): 104 | temp_index = input_count+processing_count*no_inputs 105 | input_buffer_real[temp_index].next = input_line_real 106 | input_buffer_imag[temp_index].next = input_line_imag 107 | index_mapping_array[temp_index].next = index_output #populating the index_mapping array with the index remapping array 108 | index_addr.next = index_addr+1 109 | 110 | input_count.next = input_count + 1 111 | 112 | else: #When the input buffer is full, copy the last value, trigger the processing and stall the input 113 | input_count.next = 0 114 | input_enable.next = 0 115 | processing_input_trigger.next = 1 116 | receiving_flag.next = 0 117 | stall_flag.next = 1 118 | 119 | else: 120 | if(stall_flag==1): #Stall for a clock cycle 121 | stall_flag.next = 0 122 | 123 | elif((input_trigger==1) and (processing_input_enable==1)): 124 | receiving_flag.next = 1 125 | input_enable.next = 0 126 | processing_input_trigger.next = 0 127 | 128 | elif(processing_input_enable==1): 129 | input_enable.next = 1 130 | processing_input_trigger.next = 0 131 | 132 | return receiving_logic 133 | 134 | def processing(self): 135 | """ 136 | Unscrambler processing behaviour 137 | primarily works with internal data signals 138 | """ 139 | processing_input_trigger = self.processing_input_trigger #global actor signals have to be redeclared locally for this behaviour, for conversion purposes 140 | processing_output_enable = self.processing_output_enable 141 | output_buffer_real = self.output_buffer_real 142 | output_buffer_imag = self.output_buffer_imag 143 | input_buffer_real = self.input_buffer_real 144 | input_buffer_imag = self.input_buffer_imag 145 | processing_output_trigger = self.processing_output_trigger 146 | input_enable = self.input_enable 147 | processing_input_enable = self.processing_input_enable 148 | no_inputs = self.no_inputs 149 | no_outputs = self.no_outputs 150 | reset = self.reset 151 | index_mapping_array = self.index_mapping_array 152 | clk = self.clk 153 | processing_flag = self.processing_flag 154 | processing_count = self.processing_count 155 | bit_shift = self.bit_shift 156 | 157 | busy = Signal(bool(0)) 158 | stall_flag = Signal(bool(0)) 159 | 160 | 161 | @always(clk.posedge,reset.posedge) 162 | def processing_logic(): 163 | if(reset==1): #asynchronous reset 164 | processing_output_trigger.next = 0 165 | processing_input_enable.next = 1 166 | processing_flag.next = 0 167 | busy.next = 1 168 | stall_flag.next = 0 169 | 170 | elif(processing_flag==1): 171 | if(busy==1): 172 | if(processing_count<(int(no_outputs/no_inputs)-1)): 173 | busy.next = 0 174 | processing_count.next = processing_count + 1 175 | 176 | else: 177 | busy.next = 0 178 | processing_count.next = processing_count + 1 179 | for i in range(no_outputs): 180 | output_buffer_real[i].next = (input_buffer_real[index_mapping_array[i]]>> bit_shift) #copying to the output buffer according to the index remapping 181 | output_buffer_imag[i].next = (input_buffer_imag[index_mapping_array[i]]>> bit_shift) 182 | 183 | else: 184 | processing_input_enable.next = 1 185 | processing_flag.next = 0 186 | busy.next = 1 187 | stall_flag.next = 1 188 | if(processing_count>(int(no_outputs/no_inputs)-1)): 189 | processing_output_trigger.next = 1 190 | 191 | else: 192 | if(stall_flag): stall_flag.next = 0 #stall a clock cycle 193 | 194 | elif((processing_input_trigger==1) and (processing_output_enable==1)): 195 | processing_flag.next = 1 196 | busy.next = 1 197 | processing_input_enable.next = 0 198 | processing_output_trigger.next = 0 199 | 200 | elif(processing_output_enable==1): 201 | processing_output_trigger.next = 0 202 | 203 | elif(processing_input_trigger==1): 204 | processing_input_enable.next = 0 205 | 206 | return processing_logic 207 | 208 | def logic(self): 209 | """ 210 | Unscrambler logic method 211 | calls all of the behavioural methods, for conversion purposes, as well as the remapping index memory 212 | """ 213 | index_rom_inst = self.rom(self.index_output,self.index_addr,self.index_mapping) 214 | baseclass_logic = Actor.Actor.logic(self) 215 | 216 | return instances() 217 | 218 | def rom(self,dout, addr, CONTENT): 219 | """ 220 | Unscrambler rom method 221 | creates a module for storing data 222 | """ 223 | @always_comb 224 | def read(): 225 | dout.next = CONTENT[int(addr)] 226 | 227 | return read 228 | 229 | def model(self,input_values_real,input_values_imag): 230 | """ 231 | Unscrambler model method 232 | performs the same operation as the processing method of the actor, but does it upon a Python list 233 | 234 | Parameters: 235 | input_values_real -> input list of the real values 236 | input_values_imag -> input list of the imaginary values 237 | 238 | Output: 239 | [output real values list, output imaginary values list] 240 | """ 241 | output_values_real = [] 242 | output_values_imag = [] 243 | 244 | temp_real = [] 245 | temp_imag = [] 246 | 247 | for iv in input_values_real: temp_real.extend(iv) 248 | for iv in input_values_imag: temp_imag.extend(iv) 249 | 250 | for i in range(self.no_outputs): 251 | output_values_real.append(temp_real[self.index_mapping[i]]) 252 | output_values_imag.append(temp_imag[self.index_mapping[i]]) 253 | 254 | return [[output_values_real],[output_values_imag]] 255 | 256 | 257 | -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/hdft_performance_testbench.py: -------------------------------------------------------------------------------- 1 | #HDFT Performance Evaluation Test bench 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import sys,math,HDFT,DFT_Model 7 | 8 | def Counter(clk,reset,enable,output,done,period,n): 9 | subcount = Signal(intbv(0,min=0,max=period+1)) 10 | 11 | @always(clk.posedge,reset.posedge) 12 | def inc_logic(): 13 | if(reset==1): 14 | output.next = 0 15 | done.next = 0 16 | subcount.next = 0 17 | 18 | elif((subcount<(period-1)) and (enable==0)): 19 | subcount.next = subcount + 1 20 | 21 | elif((output<(n-1)) and (enable==0)): 22 | output.next = output + 1 23 | subcount.next = 0 24 | 25 | elif(enable==1): 26 | done.next = 1 27 | 28 | return inc_logic 29 | 30 | def rom(addr,output,content): 31 | @always_comb 32 | def rom_logic(): 33 | output.next = content[addr] 34 | 35 | return rom_logic 36 | 37 | def performance_test_bench(clk,reset,microsecound_count,testdata_real,input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize): 38 | input_trigger = Signal(bool(1)) 39 | output_line_real = Signal(intbv(0,min=-2**(output_bitsize-1),max=2**(output_bitsize-1))) 40 | output_line_imag = Signal(intbv(0,min=-2**(output_bitsize-1),max=2**(output_bitsize-1))) 41 | output_trigger = Signal(bool(0)) 42 | output_enable = Signal(bool(1)) 43 | 44 | #50 MHz clock 45 | @always(delay(10)) 46 | def clock_driver(): 47 | clk.next = not(clk) 48 | #if((clk==1) and (output_trigger==1)): print "%d - %d" % (now(),output_line_real) 49 | 50 | @instance 51 | def reset_pulse_logic(): 52 | reset.next = 1 53 | yield delay(1) 54 | reset.next = 0 55 | input_trigger.next = 1 56 | output_enable.next = 1 57 | yield delay(1) 58 | 59 | #@always(output_trigger.posedge) 60 | @instance 61 | def detect_finish(): 62 | yield output_trigger 63 | print "%d - done -> %d!" % (now(),microsecound_count) 64 | 65 | @instance 66 | def start_trigger(): 67 | yield delay(5) 68 | input_trigger.next = 1 69 | 70 | hdft_tb_inst = hdft_test_bench(clk,reset,microsecound_count,input_trigger,output_line_real,output_line_imag,output_trigger,output_enable,testdata_real,input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize) 71 | 72 | return instances() 73 | 74 | def hdft_test_bench(clk,reset,microsecound_count,input_trigger,output_line_real,output_line_imag,output_trigger,output_enable,testdata_real,input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize): 75 | input_line_real = Signal(intbv(0,min=-2**(input_bitsize-1),max=2**(input_bitsize-1))) 76 | input_line_imag = Signal(intbv(0,min=-2**(input_bitsize-1),max=2**(input_bitsize-1))) 77 | input_enable = Signal(bool(1)) 78 | 79 | input_rom_signal = Signal(intbv(0,min=0,max=len(testdata_real)+1)) 80 | input_done_flag = Signal(bool(0)) 81 | performance_done_flag = Signal(bool(0)) 82 | 83 | input_rom = rom(input_rom_signal,input_line_real,tuple(testdata_real)) 84 | input_counter = Counter(clk,reset,output_trigger,input_rom_signal,input_done_flag,0,len(testdata_real)) 85 | performance_counter = Counter(clk,reset,output_trigger,microsecound_count,performance_done_flag,50,256) 86 | 87 | no_inputs = len(testdata_real) 88 | no_outputs = no_inputs 89 | hdft_inst = HDFT.HDFT(input_line_real,input_line_imag,input_trigger,input_enable,no_inputs,output_line_real,output_line_imag,output_trigger,output_enable,no_outputs,reset,clk,input_bitsize,output_bitsize,twiddle_bitsize,dft_bitsize,dft_size) 90 | hdft_logic_inst = hdft_inst.logic(input_line_real,input_line_imag,input_trigger,input_enable,output_line_real,output_line_imag,output_trigger,output_enable,clk,reset) 91 | 92 | return instances() 93 | 94 | print "Hybrid DFT Performance Evaluation Test Bench" 95 | print "usage: python system_dev_testbench.py [input filename] [input bit width] [twiddle factor bit width] [DFT Size] [Multiplier input bit width] [Output bit width]" 96 | 97 | input_file = open(sys.argv[1]) 98 | input_bitsize = int(sys.argv[2]) 99 | twiddle_bitsize = int(sys.argv[3]) 100 | dft_size = int(sys.argv[4]) 101 | dft_bitsize = int(sys.argv[5]) 102 | output_bitsize = int(sys.argv[6]) 103 | 104 | hdft_model = DFT_Model.HybridFFTDFT(input_file,"",input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize) 105 | hdft_model.readdata() 106 | 107 | #test data read in from file 108 | testdata_real = map(int,hdft_model.input_values_real) 109 | 110 | clk = Signal(bool(0)) 111 | reset = Signal(bool(0)) 112 | 113 | microsecound_count = Signal(intbv(0)[8:]) 114 | 115 | signal_trace = traceSignals(performance_test_bench,clk,reset,microsecound_count,testdata_real,input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize) 116 | sim = Simulation(signal_trace) 117 | sim.run(100000) 118 | 119 | input_trigger = Signal(bool(1)) 120 | output_line_real = Signal(intbv(0,min=-2**(output_bitsize-1),max=2**(output_bitsize-1))) 121 | output_line_imag = Signal(intbv(0,min=-2**(output_bitsize-1),max=2**(output_bitsize-1))) 122 | output_trigger = Signal(bool(0)) 123 | output_enable = Signal(bool(1)) 124 | 125 | #toVerilog(hdft_test_bench,clk,reset,microsecound_count,input_trigger,output_line_real,output_line_imag,output_trigger,output_enable,testdata_real,input_bitsize,twiddle_bitsize,dft_size,dft_bitsize,output_bitsize) -------------------------------------------------------------------------------- /Toolflow_Code/Old_HDFT_Code/system_dev_testbench.py: -------------------------------------------------------------------------------- 1 | #System Development Test bench 2 | #Rhino Project Software Defined Radio Toolflow 3 | #Gordon Inggs 4 | #March 2011 5 | from myhdl import * 6 | import HDFT,DFT_Model,sys 7 | 8 | def test_bench_hdft(hdft_inst,input_line_real,input_line_imag,input_trigger,input_enable,output_line_real,output_line_imag,output_trigger,output_enable,clk,reset,outputdata_real,outputdata_imag,testdata_real,testdata_imag): 9 | hdft_logic_inst = hdft_inst.logic() 10 | 11 | @always(delay(5)) 12 | def clock_driver(): 13 | clk.next = not(clk) 14 | #print "%d: clock value - %d" % (now(),clk) 15 | 16 | @instance 17 | def reset_pulse_logic(): 18 | reset.next = 1 19 | #print now() 20 | yield delay(1) 21 | #print now() 22 | reset.next = 0 23 | yield delay(1) 24 | #print now() 25 | 26 | input_count = Signal(intbv(0)) 27 | input_set_count = Signal(intbv(0)) 28 | transmit_flag = Signal(bool(0)) 29 | done = Signal(bool(0)) 30 | 31 | @always(clk.posedge,reset.posedge) 32 | def input_logic(): 33 | #yield delay(int(1*random.random())+1) 34 | if(reset): 35 | input_count.next = 0 36 | input_set_count.next = 0 37 | 38 | else: 39 | #print "inputing set %d" % input_set_count 40 | #input_trigger.next = 0 41 | if(transmit_flag or input_enable and not(done)): 42 | if(not(transmit_flag)): 43 | transmit_flag.next = 1 44 | input_trigger.next = 1 45 | 46 | elif((input_count<(len(testdata_real[input_set_count]))) and (input_set_count<(len(testdata_real)))): 47 | #print "%d: input logic - %d" % (now(),input_count) 48 | input_line_real.next = testdata_real[input_set_count][input_count] 49 | input_line_imag.next = testdata_imag[input_set_count][input_count] 50 | input_count.next = input_count + 1 51 | 52 | elif((input_set_count<(len(testdata_real)-1))): 53 | transmit_flag.next = 0 54 | input_trigger.next = 0 55 | input_count.next = 0 56 | input_set_count.next = input_set_count + 1 57 | 58 | else: 59 | transmit_flag.next = 0 60 | input_trigger.next = 0 61 | done.next = 1 62 | 63 | else: 64 | input_trigger.next = 0 65 | 66 | output_count = Signal(intbv(0)) 67 | output_set_count = Signal(intbv(0)) 68 | outputdata_real.append([]) 69 | outputdata_imag.append([]) 70 | receive_flag = Signal(bool(0)) 71 | 72 | no_output_values = len(testdata_real[output_set_count]) 73 | no_output_value_sets = len(testdata_real) 74 | 75 | @always(clk.posedge) 76 | def output_logic(): 77 | if(output_set_count<(no_output_value_sets)): 78 | output_enable.next = 1 79 | 80 | else: 81 | output_enable.next = 0 82 | 83 | if(output_trigger and (output_set_count